diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/fs/ScanfFormatStringSecurityChecker.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/fs/ScanfFormatStringSecurityChecker.java index ab1b954cd3c..a16509d6f5e 100644 --- a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/fs/ScanfFormatStringSecurityChecker.java +++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/fs/ScanfFormatStringSecurityChecker.java @@ -165,7 +165,7 @@ public class ScanfFormatStringSecurityChecker extends AbstractIndexAstChecker { IType expressionType = idExpression.getExpressionType(); if (expressionType instanceof IArrayType) { IArrayType arrayExpressionType = (IArrayType) expressionType; - long arraySize = arrayExpressionType.getSize().numericalValue().longValue(); + long arraySize = arrayExpressionType.getSize().numberValue().longValue(); if (argumentSize > arraySize) { reportProblem(ER_ID, idExpression, idExpression.getRawSignature()); } diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java index c1da6a39871..0fcac765920 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/internal/model/cfg/ControlFlowGraphBuilder.java @@ -60,7 +60,7 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.osgi.util.NLS; /** @@ -581,11 +581,11 @@ public class ControlFlowGraphBuilder { if (node instanceof ICfgData) { IASTNode ast = (IASTNode) ((ICfgData) node).getData(); if (ast instanceof IASTExpression) { - IValue dvalue = Value.create((IASTExpression) ast); - Long numericalValue = dvalue.numericalValue(); + IValue dvalue = ValueFactory.create((IASTExpression) ast); + Number numericalValue = dvalue.numberValue(); if (numericalValue == null) return false; - return numericalValue == testvalue; + return numericalValue.longValue() == testvalue; } } return false; 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 c55052f03a9..7328cf80177 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 @@ -7789,11 +7789,11 @@ public class AST2CPPTests extends AST2TestBase { public void testCastInEnumeratorValue_446380() throws Exception { BindingAssertionHelper ba= getAssertionHelper(); IEnumerator i2 = ba.assertNonProblem("i2", IEnumerator.class); - Long v2 = i2.getValue().numericalValue(); + Number v2 = i2.getValue().numberValue(); assertNotNull(v2); assertEquals(1, v2.intValue()); IEnumerator i3 = ba.assertNonProblem("i3", IEnumerator.class); - Long v3 = i3.getValue().numericalValue(); + Number v3 = i3.getValue().numberValue(); assertNotNull(v3); assertEquals(2, v3.intValue()); ICPPFunction f = ba.assertNonProblemOnFirstIdentifier("f(i3)",ICPPFunction.class); @@ -11302,7 +11302,7 @@ public class AST2CPPTests extends AST2TestBase { // to its end, the IDE would appear to hang. BindingAssertionHelper helper = getAssertionHelper(); IVariable waldo = helper.assertNonProblem("waldo"); - assertNull(waldo.getInitialValue().numericalValue()); + assertNull(waldo.getInitialValue().numberValue()); } // constexpr int foo(int a = 42) { @@ -11956,6 +11956,43 @@ public class AST2CPPTests extends AST2TestBase { public void testEnumDeclaredLaterInClass_491747() throws Exception { parseAndCheckBindings(); } + + // class S { + // static S waldo; + // }; + // void foo(const S& = S()); + public void testValueRepresentationOfClassWithStaticMemberOfOwnType_490475() throws Exception { + BindingAssertionHelper helper = getAssertionHelper(); + ICPPFunction foo = helper.assertNonProblem("foo"); + // Trigger computation of value representation of S(). + foo.getParameters()[0].getDefaultValue(); + } + + // class S { + // S waldo; // invalid + // }; + // void foo(const S& = S()); + public void testClassDirectlyAggregatingItself_490475() throws Exception { + BindingAssertionHelper helper = getAssertionHelper(); + ICPPFunction foo = helper.assertNonProblem("foo"); + // Trigger computation of value representation of S(). + foo.getParameters()[0].getDefaultValue(); + } + + // class T; + // class S { + // T waldo; // invalid + // }; + // class T { + // S waldo; + // }; + // void foo(const T& = T()); + public void testClassIndirectlyAggregatingItself_490475() throws Exception { + BindingAssertionHelper helper = getAssertionHelper(); + ICPPFunction foo = helper.assertNonProblem("foo"); + // Trigger computation of value representation of S(). + foo.getParameters()[0].getDefaultValue(); + } // namespace std { // template class initializer_list; 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 15aa882b93a..e0aad1d4818 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 @@ -94,7 +94,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; @@ -3077,12 +3077,12 @@ public class AST2TemplateTests extends AST2TestBase { ICPPTemplateInstance ci1= assertInstance(t.getType(), ICPPTemplateInstance.class, ICPPClassType.class); ICPPTemplateParameterMap args1= ci1.getTemplateParameterMap(); assertEquals(1, args1.getAllParameterPositions().length); - assertEquals(256, args1.getArgument(0).getNonTypeValue().numericalValue().intValue()); + assertEquals(256, args1.getArgument(0).getNonTypeValue().numberValue().intValue()); ICPPTemplateInstance ct= ba.assertNonProblem("C<_256> ", 7, ICPPTemplateInstance.class, ICPPClassType.class); ICPPTemplateParameterMap args= ct.getTemplateParameterMap(); assertEquals(1, args.getAllParameterPositions().length); - assertEquals(256, args.getArgument(0).getNonTypeValue().numericalValue().intValue()); + assertEquals(256, args.getArgument(0).getNonTypeValue().numberValue().intValue()); ba.assertNonProblem("foo(t)", 3); ba.assertNonProblem("bar(t)", 3); @@ -3101,7 +3101,7 @@ public class AST2TemplateTests extends AST2TestBase { ICPPDeferredClassInstance ci= ba.assertNonProblem("C", 4, ICPPDeferredClassInstance.class); ICPPTemplateArgument[] args= ci.getTemplateArguments(); assertEquals(1, args.length); - assertEquals(0, Value.isTemplateParameter(args[0].getNonTypeValue())); + assertEquals(0, IntegralValue.isTemplateParameter(args[0].getNonTypeValue())); } // template @@ -6961,8 +6961,8 @@ public class AST2TemplateTests extends AST2TestBase { ICPPSpecialization buffRef = assertionHelper.assertNonProblem("myA.buff[0] = 1;", "buff", ICPPSpecialization.class); assertEquals(buff, buffRef.getSpecializedBinding()); - assertEquals(Long.valueOf(4),buffRef.getTemplateParameterMap().getArgument(0).getNonTypeValue().numericalValue()); - assertEquals(Long.valueOf(5),buffRef.getTemplateParameterMap().getArgument(1).getNonTypeValue().numericalValue()); + assertEquals(Long.valueOf(4),buffRef.getTemplateParameterMap().getArgument(0).getNonTypeValue().numberValue()); + assertEquals(Long.valueOf(5),buffRef.getTemplateParameterMap().getArgument(1).getNonTypeValue().numberValue()); } // template @@ -6986,7 +6986,7 @@ public class AST2TemplateTests extends AST2TestBase { assertEquals(buff, buffRef.getSpecializedBinding()); assertSameType(buffRef.getTemplateParameterMap().getArgument(0).getTypeValue(), new CPPBasicType(IBasicType.Kind.eInt, 0)); - assertEquals(Long.valueOf(5),buffRef.getTemplateParameterMap().getArgument(1).getNonTypeValue().numericalValue()); + assertEquals(Long.valueOf(5),buffRef.getTemplateParameterMap().getArgument(1).getNonTypeValue().numberValue()); } // template @@ -8008,7 +8008,7 @@ public class AST2TemplateTests extends AST2TestBase { BindingAssertionHelper ah = getAssertionHelper(); IEnumerator binding = ah.assertNonProblem("C::id", "id"); IValue value = binding.getValue(); - Long num = value.numericalValue(); + Number num = value.numberValue(); assertNotNull(num); assertEquals(1, num.longValue()); } @@ -9433,6 +9433,7 @@ public class AST2TemplateTests extends AST2TestBase { // // template // struct D { + // D(T); // T t; // }; // @@ -9602,4 +9603,43 @@ public class AST2TemplateTests extends AST2TestBase { public void testDisambiguationInNoexceptSpecifier_467332() throws Exception { parseAndCheckBindings(); } + + // template + // struct C { + // T field; + // void meow(); + // }; + // struct S { + // template + // auto operator()(U u) -> decltype(C{u}); + // }; + // int main() { + // S()(0).meow(); // ERROR: Method 'meow' could not be resolved + // } + public void testBraceInitialization_490475a() throws Exception { + parseAndCheckBindings(); + } + + // struct S { + // int x; + // int y; + // }; + // + // constexpr int foo(S a, S b) { + // return a.x - b.x; + // } + // + // constexpr S a = S{8, 0}; + // constexpr S b = S{21, 0}; + // + // constexpr int waldo = foo(a, b); + public void testBraceInitialization_490475b() throws Exception { + BindingAssertionHelper helper = getAssertionHelper(); + IVariable waldo = helper.assertNonProblem("waldo"); + // TODO(nathanridge): + // Actually test that we get the correct value. + // For this, we need to add support for aggregate initialization in EvalTypeId. + // For now, just test that attempting to evaluate doesn't throw an exception. + waldo.getInitialValue(); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java index 897be32253c..574fbefbe8f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java @@ -514,7 +514,7 @@ public class AST2TestBase extends BaseTestCase { protected static void assertConstantValue(long expected, IVariable constant) { IValue value = constant.getInitialValue(); assertNotNull(value); - Long numericalValue = value.numericalValue(); + Number numericalValue = value.numberValue(); assertNotNull(numericalValue); assertEquals(expected, numericalValue.longValue()); } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index a7e89354295..26c7d00bfac 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -5752,7 +5752,7 @@ public class AST2Tests extends AST2TestBase { v= (IVariable) bh.assertNonProblem("b=", 1); checkValue(v.getInitialValue(), 0); v= (IVariable) bh.assertNonProblem("c=", 1); - assertNull(v.getInitialValue().numericalValue()); + assertNull(v.getInitialValue().numberValue()); IEnumerator e= (IEnumerator) bh.assertNonProblem("e0", 2); checkValue(e.getValue(), 0); @@ -5769,7 +5769,7 @@ public class AST2Tests extends AST2TestBase { private void checkValue(IValue initialValue, int i) { assertNotNull(initialValue); - final Long numericalValue = initialValue.numericalValue(); + final Number numericalValue = initialValue.numberValue(); assertNotNull(numericalValue); assertEquals(i, numericalValue.intValue()); } @@ -6976,10 +6976,10 @@ public class AST2Tests extends AST2TestBase { IASTEnumerationSpecifier enumSpec = (IASTEnumerationSpecifier)((IASTSimpleDeclaration) tu.getDeclarations()[0]).getDeclSpecifier(); IEnumerator enumeratorBinding = (IEnumerator) enumSpec.getEnumerators()[0].getName().resolveBinding(); IValue value = enumeratorBinding.getValue(); - assertEquals(2, value.numericalValue().longValue()); + assertEquals(2, value.numberValue().longValue()); IEnumerator enumeratorBinding2 = (IEnumerator) enumSpec.getEnumerators()[1].getName().resolveBinding(); IValue value2 = enumeratorBinding2.getValue(); - assertEquals(1, value2.numericalValue().longValue()); + assertEquals(1, value2.numberValue().longValue()); } } @@ -7413,7 +7413,8 @@ public class AST2Tests extends AST2TestBase { ITypedef tdef= (ITypedef) sdecl.getDeclarators()[0].getName().resolveBinding(); IArrayType at= (IArrayType) tdef.getType(); IValue v= at.getSize(); - assertTrue(v.numericalValue() == 4); + assertNotNull(v.numberValue()); + assertTrue(v.numberValue().longValue() == 4); } } @@ -7500,7 +7501,7 @@ public class AST2Tests extends AST2TestBase { BindingAssertionHelper helper = new BindingAssertionHelper(code, true); ICPPTemplateInstance f = helper.assertNonProblem("f(STRINGIFY", "f"); // 7 characters for "foobar" + the null terminator. - assertEquals(7, f.getTemplateArguments()[0].getNonTypeValue().numericalValue().longValue()); + assertEquals(7, f.getTemplateArguments()[0].getNonTypeValue().numberValue().longValue()); } // typedef unsigned char u8; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/AllConstexprEvalTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/AllConstexprEvalTests.java new file mode 100644 index 00000000000..e995f20f8a5 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/AllConstexprEvalTests.java @@ -0,0 +1,67 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AllConstexprEvalTests { + public static Test suite() throws Exception { + final TestSuite suite = new TestSuite(); + suite.addTest(ConstructorTests.NonIndexing.suite()); + suite.addTest(ConstructorTests.SingleProject.suite()); + suite.addTest(MemberFunctionTests.NonIndexing.suite()); + suite.addTest(MemberFunctionTests.SingleProject.suite()); + suite.addTest(MemberVariableTests.NonIndexing.suite()); + suite.addTest(MemberVariableTests.SingleProject.suite()); + suite.addTest(FunctionTests.NonIndexing.suite()); + suite.addTest(FunctionTests.SingleProject.suite()); + suite.addTest(FunctionTemplateTests.NonIndexing.suite()); + suite.addTest(FunctionTemplateTests.SingleProject.suite()); + suite.addTest(ClassTemplateTests.NonIndexing.suite()); + suite.addTest(ClassTemplateTests.SingleProject.suite()); + suite.addTest(IfStatementTests.NonIndexing.suite()); + suite.addTest(IfStatementTests.SingleProject.suite()); + suite.addTest(SwitchStatementTests.NonIndexing.suite()); + suite.addTest(SwitchStatementTests.SingleProject.suite()); + suite.addTest(WhileStatementTests.NonIndexing.suite()); + suite.addTest(WhileStatementTests.SingleProject.suite()); + suite.addTest(DoWhileStatementTests.NonIndexing.suite()); + suite.addTest(DoWhileStatementTests.SingleProject.suite()); + suite.addTest(ForStatementTests.NonIndexing.suite()); + suite.addTest(ForStatementTests.SingleProject.suite()); + suite.addTest(RangeBasedForStatementTests.NonIndexing.suite()); + suite.addTest(RangeBasedForStatementTests.SingleProject.suite()); + suite.addTest(BinaryOperatorOverloadingTests.NonIndexing.suite()); + suite.addTest(BinaryOperatorOverloadingTests.SingleProject.suite()); + suite.addTest(UnaryOperatorOverloadingTests.NonIndexing.suite()); + suite.addTest(UnaryOperatorOverloadingTests.SingleProject.suite()); + suite.addTest(ArrayTests.NonIndexing.suite()); + suite.addTest(ArrayTests.SingleProject.suite()); + suite.addTest(BinaryExpressionTests.NonIndexing.suite()); + suite.addTest(BinaryExpressionTests.SingleProject.suite()); + suite.addTest(UnaryExpressionTests.NonIndexing.suite()); + suite.addTest(UnaryExpressionTests.SingleProject.suite()); + suite.addTest(ReferenceTests.NonIndexing.suite()); + suite.addTest(ReferenceTests.SingleProject.suite()); + suite.addTest(TypeAliasTests.NonIndexing.suite()); + suite.addTest(TypeAliasTests.SingleProject.suite()); + suite.addTest(PointerTests.NonIndexing.suite()); + suite.addTest(PointerTests.SingleProject.suite()); + suite.addTest(UserDefinedLiteralTests.NonIndexing.suite()); + suite.addTest(UserDefinedLiteralTests.SingleProject.suite()); + suite.addTest(IntegralValueTests.NonIndexing.suite()); + suite.addTest(IntegralValueTests.SingleProject.suite()); + suite.addTest(FloatingPointValueTests.NonIndexing.suite()); + suite.addTest(FloatingPointValueTests.SingleProject.suite()); + suite.addTest(CStringValueTests.NonIndexing.suite()); + suite.addTest(CStringValueTests.SingleProject.suite()); + return suite; + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ArrayTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ArrayTests.java new file mode 100644 index 00000000000..cf5e5a651f1 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ArrayTests.java @@ -0,0 +1,244 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class ArrayTests extends TestBase { + public static class NonIndexing extends ArrayTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends ArrayTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int f() { + // int foo[3][2] { {1,2}, {2, 3},{ 4, 5} }; + // return foo[2][1]; + // } + + // constexpr int x = f(); + public void testInitializationOfMultiDimensionalArrays() throws Exception { + assertEvaluationEquals(5); + } + + // constexpr int f() { + // int foo[3] { 1, 2, 3 }; + // foo[1] = foo[0] + foo[2]; + // return foo[1]; + // } + + // constexpr int x = f(); + public void testAssignmentOfArrays() throws Exception { + assertEvaluationEquals(4); + } + + // constexpr int f() { + // int foo[3][2] { {1,2}, {2, 3},{ 4, 5} }; + // foo[0][1] = 3; + // return foo[0][1]; + // } + + // constexpr int x = f(); + public void testAssignmentOfMultiDimensionalArrays() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int a[2][2] { { 1, 2 }, { 3, 4 } }; + // constexpr int f() { + // return a[0][0]; + // } + + // constexpr auto x = f(); + public void testGlobalArrayAccessValue() throws Exception { + assertEvaluationEquals(1); + } + + // constexpr int f() { + // int x[2][2] { { 1, 2 }, { 3, 4 } }; + // int &xref { x[1][1] }; + // int &xref2 { x[1][1] }; + // xref++; + // xref = xref * xref2; + // return x[1][1]; + // } + + // constexpr auto x = f(); + public void testReferenceToArrayCell() throws Exception { + assertEvaluationEquals(25); + } + + // constexpr int f() { + // int bar[2] { 3, 7 }; + // (*bar)++; + // return bar[0]; + // } + + // constexpr int x = f(); + public void testPointerDereferencingOnArrayName() throws Exception { + assertEvaluationEquals(4); + } + + // class S { + // int arr[4]; + // public: + // constexpr S():arr{5,6,7,8} {} + // constexpr int *getPtr() { + // return arr; + // } + // }; + // constexpr int f() { + // S s{}; + // int *ptr = s.getPtr(); + // return *ptr; + // } + + // constexpr int x = f(); + public void testPointerToArrayReturnedFromMemberFunction1() throws Exception { + assertEvaluationEquals(5); + } + + // class S { + // int arr[4]; + // public: + // constexpr S():arr{5,7,9,11} {} + // constexpr int *getPtr() { + // return arr; + // } + // }; + // constexpr int f() { + // S s{}; + // int *ptr = s.getPtr(); + // ptr += 2; + // return *ptr; + // } + + // constexpr int x = f(); + public void testPointerToArrayReturnedFromMemberFunction2() throws Exception { + assertEvaluationEquals(9); + } + + // class S { + // int arr[4]; + // public: + // constexpr S():arr{5,7,9,11} {} + // constexpr int *getBegin() { + // return arr; + // } + // constexpr int *getEnd() { + // return arr + 4; + // } + // }; + // + // constexpr int f() { + // S s{}; + // int *begin = s.getBegin(); + // int *end = s.getEnd(); + // int sum = 0; + // for(; begin != end; begin++) { + // sum += *begin; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testPointerToArrayReturnedFromMemberFunction3() throws Exception { + assertEvaluationEquals(32); + } + + // constexpr int f() { + // int arr[] = {1, 2, 3}; + // int (&arrRef)[3] = arr; + // return arrRef[2]; + // } + + // constexpr int x = f(); + public void testReferenceToArray1() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int f() { + // int arr[] = {1, 2, 3}; + // int (&arrRef)[3] = arr; + // arrRef[2] *= 2; + // return arr[2]; + // } + + // constexpr int x = f(); + public void testReferenceToArray2() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr int f() { + // int arr[] = {1, 2, 3}; + // int (&arrRef)[3] = arr; + // for(int& i : arrRef) { + // i *= 2; + // } + // return arr[2]; + // } + + // constexpr int x = f(); + public void testReferenceToArray3() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr int f() { + // int bar[2][2] { { 3, 5 }, {7, 11 } }; + // int * bar_ptr { bar[1] }; + // (*bar_ptr)++; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerArithmeticsOnMultidimensionalArray() throws Exception { + assertEvaluationEquals(8); + } + + // constexpr void g(int * array) { + // array[0] = 1337; + // } + // constexpr int f() { + // int bar[2] { 1, 2 }; + // g(bar); + // return bar[0]; + // } + + // constexpr int x = f(); + public void testPassArrayToFunctionAsPointerAndModifyCell() throws Exception { + assertEvaluationEquals(1337); + } + + // constexpr void g(int array[2][2]) { + // array[1][0] = 1337; + // } + // constexpr int f() { + // int bar[2][2] { { 3, 5 }, { 7, 11 } }; + // g(bar); + // return bar[1][0]; + // } + + // constexpr int x = f(); + public void testPassMultiDimensionalArrayToFunctionAsPointerAndModifyCell() throws Exception { + assertEvaluationEquals(1337); + } + + // constexpr int f() { + // int foo[] { 1, 2, 3, 4, 5 }; + // return foo[2]; + // } + + // constexpr int x = f(); + public void testInitializationOfArrays() throws Exception { + assertEvaluationEquals(3); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/BinaryExpressionTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/BinaryExpressionTests.java new file mode 100644 index 00000000000..d8276d0dc3a --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/BinaryExpressionTests.java @@ -0,0 +1,55 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class BinaryExpressionTests extends TestBase { + public static class NonIndexing extends BinaryExpressionTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends BinaryExpressionTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr bool f() { + // bool a { true }; + // return a && false; + // } + + // constexpr int x = f(); + public void testSimpleBooleanValues() throws Exception { + assertEvaluationEquals(false); + } + + // constexpr int f() { + // int x = 5; + // (x=3)++; + // return x; + // } + + // constexpr auto x = f(); + public void testAssignmentReturnsLValue() throws Exception { + assertEvaluationEquals(4); + } + + // constexpr int addTwice(int op1, int op2) { + // op1 += op2; + // op1 += op2; + // return op1; + // } + + // constexpr int x = addTwice(2, 5); + public void testBinaryExpressionSequence() throws Exception { + assertEvaluationEquals(12); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/BinaryOperatorOverloadingTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/BinaryOperatorOverloadingTests.java new file mode 100644 index 00000000000..d3e633e70d8 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/BinaryOperatorOverloadingTests.java @@ -0,0 +1,188 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class BinaryOperatorOverloadingTests extends TestBase { + public static class NonIndexing extends BinaryOperatorOverloadingTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends BinaryOperatorOverloadingTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // struct S { + // constexpr S(int x):x{x} {} + // constexpr int operator+(S const& other) { + // return 12; + // } + // private: + // int x; + // }; + // + // constexpr int f() { + // S s1{2}; + // S s2{3}; + // int x = s1 + s2; + // return x; + // } + + // constexpr int x = f(); + public void testOverloadedPlusOperatorAsMemberFunction() throws Exception { + assertEvaluationEquals(12); + } + + // struct S { + // constexpr S(int x):x{x} {} + // constexpr S operator*(S const& other) { + // return S{x * other.x * 2}; + // } + // int x; + // }; + // + // constexpr int f() { + // S s1{2}; + // S s2{3}; + // S s3 = s1 * s2; + // return s3.x; + // } + + // constexpr int x = f(); + public void testOverloadedMultiplicationOperatorAsMemberFunction() throws Exception { + assertEvaluationEquals(12); + } + + // struct S { + // constexpr S(int x, int y):x{x}, y{y} {} + // int x, y; + // }; + // constexpr S operator+(S const& s1, S const& s2) { + // return S{s1.x + s2.x + 2, s1.y + s2.y + 4}; + // } + // + // constexpr int f() { + // S s1{2, 4}; + // S s2{3, 6}; + // S s3 = s1 + s2; + // return s3.y; + // } + + // constexpr int x = f(); + public void testOverloadedPlusOperatorAsNonMemberFunction() throws Exception { + assertEvaluationEquals(14); + } + + // struct S { + // constexpr S(int x, int y):x{x*2}, y{y+1} { + // } + // constexpr S operator+(S const& other) { + // S result{x + other.x, y + other.y*2}; + // return result; + // } + // int x, y; + // }; + // constexpr int f() { + // S s1{2,4}; + // S s2{4,8}; + // S result{s1 + s2}; + // return result.y; + // } + + // constexpr int x = f(); + public void testOverloadedOperatorPlusComplex1() throws Exception { + assertEvaluationEquals(24); + } + + // struct S { + // constexpr S(int x, int y):x{x*2}, y{y+1} { + // } + // constexpr S operator+(S const& other) { + // S result{x + other.x, y + other.y*2}; + // return result; + // } + // int x, y; + // }; + // constexpr int f() { + // S s1{2,4}; + // S s2{4,8}; + // S result = s1 + s2; + // return result.x; + // } + + // constexpr int x = f(); + public void testOverloadedOperatorPlusComplex2() throws Exception { + assertEvaluationEquals(24); + } + + // struct S { + // constexpr S(int x, int y):x{x*2}, y{y+1} { + // } + // constexpr S operator+(S const& other) { + // return S{x + other.x, y + other.y*2}; + // } + // int x, y; + // }; + // constexpr int f() { + // S s1{2,4}; + // S s2{4,8}; + // S result{s1 + s2}; + // return result.y; + // } + + // constexpr int x = f(); + public void testOverloadedOperatorPlusComplex3() throws Exception { + assertEvaluationEquals(24); + } + + // class Point { + // int x, y; + // public: + // constexpr Point(int x, int y):x{x}, y{y} {} + // constexpr bool operator==(Point const& other) const { + // return x == other.x && y == other.y; + // } + // }; + // constexpr int f() { + // Point p1{2,4}; + // Point p2{2,4}; + // return p1 == p2 ? 20 : 40; + // } + + // constexpr int x = f(); + public void testOverloadedOperatorEquals() throws Exception { + assertEvaluationEquals(20); + } + + // class Point { + // int x, y; + // public: + // constexpr Point(int x, int y):x{x}, y{y} {} + // constexpr Point& operator=(Point const& other) { + // x = 2 * other.x; + // y = 2 * other.y; + // return *this; + // } + // constexpr int getY() const { return y; } + // }; + // constexpr int f() { + // Point p1{0, 0}; + // Point p2{2,5}; + // p1 = p2; + // return p1.getY(); + // } + + // constexpr int x = f(); + public void testOverloadedOperatorAssign() throws Exception { + assertEvaluationEquals(10); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/CStringValueTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/CStringValueTests.java new file mode 100644 index 00000000000..28513e676b2 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/CStringValueTests.java @@ -0,0 +1,98 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class CStringValueTests extends TestBase { + public static class NonIndexing extends CStringValueTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends CStringValueTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr auto x = "Hello, World!"; + public void testWithoutPrefix() throws Exception { + assertEvaluationEquals("Hello, World!"); + } + + // constexpr auto y = "Hello, World!"; + + // constexpr auto x = y; + public void testStringAssignment() throws Exception { + assertEvaluationEquals("Hello, World!"); + } + + // constexpr auto x = L"Hello, World!"; + public void testLPrefix() throws Exception { + assertEvaluationEquals("Hello, World!"); + } + + // constexpr auto x = u8"Hello, World!"; + public void testu8Prefix() throws Exception { + assertEvaluationEquals("Hello, World!"); + } + + // constexpr auto x = u"Hello, World!"; + public void testuPrefix() throws Exception { + assertEvaluationEquals("Hello, World!"); + } + + // constexpr auto x = U"Hello, World!"; + public void testUPrefix() throws Exception { + assertEvaluationEquals("Hello, World!"); + } + + //constexpr auto x = R"(This is + //a "raw" \n\n + // literal\0end)"; + public void testRawStringLiteral() throws Exception { + assertEvaluationEquals("This is\na \"raw\" \\n\\n\n\tliteral\\0end"); + } + + //constexpr auto x = R"ab(This is)" + //a "raw" literal)ab"; + public void testRawStringLiteralWithDelimiter() throws Exception { + assertEvaluationEquals("This is)\"\na \"raw\" literal"); + } + + // constexpr auto x = "line 1\n" + // "line 2\n" + // "line 3"; + public void testCStringLiteralConcatenation() throws Exception { + assertEvaluationEquals("line 1\nline 2\nline 3"); + } + + // constexpr auto x = "PI = \u03C0"; + public void test16bitUnicodeEscapeSequence() throws Exception { + assertEvaluationEquals("PI = \u03C0"); + } + + // constexpr int len(const char *str) { + // int len = 0; + // while(str[len] != '\0') { + // len++; + // } + // return len; + // } + // + // constexpr int f() { + // const char *str = "hello"; + // return len(str); + // } + + // constexpr int x = f(); + public void testCStringParam() throws Exception { + assertEvaluationEquals(5); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ClassTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ClassTemplateTests.java new file mode 100644 index 00000000000..396a4f2112d --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ClassTemplateTests.java @@ -0,0 +1,150 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class ClassTemplateTests extends TestBase { + public static class NonIndexing extends ClassTemplateTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends ClassTemplateTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // template + // struct Point { + // T x; + // T y; + // constexpr T len() { + // return x * x + y * y; + // } + // }; + // constexpr int f() { + // Point a{3,4} ; + // return a.len(); + // } + + // constexpr int x = f(); + public void testInstantiationOfClassTemplate() throws Exception { + assertEvaluationEquals(25); + } + + // template + // struct Multiplier { + // int y; + // constexpr int product() { + // return X * y; + // } + // }; + // constexpr int f() { + // Multiplier<5> m{7}; + // return m.product(); + // } + + // constexpr int x = f(); + public void testInstantiationOfClassTemplateWithNontypeTemplateParameter1() throws Exception { + assertEvaluationEquals(35); + } + + // template + // struct Multiplier { + // int x = X; + // int y = Y; + // constexpr int product() { + // return x * y; + // } + // }; + // constexpr int f() { + // Multiplier<5, 7> m{}; + // return m.product(); + // } + + // constexpr int x = f(); + public void testInstantiationOfClassTemplateWithNontypeTemplateParameter2() throws Exception { + assertEvaluationEquals(35); + } + + // template + // struct Adder { + // constexpr int sum() { + // return X + Y; + // } + // }; + // + // template + // using FiveAdder = Adder<5, Y>; + // + // constexpr int f() { + // FiveAdder<12> adder{}; + // return adder.sum(); + // } + + // constexpr int x = f(); + public void testAliasTemplate1() throws Exception { + assertEvaluationEquals(17); + } + + // template + // struct X { + // constexpr int get() const { + // return T; + // } + // }; + // template + // struct S : X<2*T> { + // }; + // constexpr int f() { + // S<5> s{}; + // return s.get(); + // } + + // constexpr int x = f(); + public void testInstantiationOfBaseClassTemplate1() throws Exception { + assertEvaluationEquals(10); + } + + // template + // struct X { + // int x = 2*T; + // }; + // template + // struct S : X { + // constexpr int get() const { + // return 3 * this->x; + // } + // }; + // constexpr int f() { + // S<5> s{}; + // return s.get(); + // } + // constexpr int x = f(); + public void testInstantiationOfBaseClassTemplate2() throws Exception { + assertEvaluationEquals(30); + } + + // template + // struct S { + // constexpr S():x{I*2} {} + // int x; + // }; + // + // constexpr int f() { + // S<5> s{}; + // return s.x; + // } + + // constexpr int x = f(); + public void testTemplateArgumentInMemberInitializerList() throws Exception { + assertEvaluationEquals(10); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ConstructorTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ConstructorTests.java new file mode 100644 index 00000000000..f1b1c6b13a8 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ConstructorTests.java @@ -0,0 +1,557 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; + +import junit.framework.TestSuite; + +public class ConstructorTests extends TestBase { + public static class NonIndexing extends ConstructorTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends ConstructorTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // struct S { + // int x; + // constexpr S(int i) : x{i*i} {} + // }; + // constexpr auto f() { + // S s(5); + // return s.x; + // } + + // constexpr auto x = f(); + public void testConstexprConstructorChainInitializers() throws Exception { + assertEvaluationEquals(25); + } + + // struct S { + // int x; + // constexpr S(int i) : x{i*i} { x++; } + // }; + // constexpr auto f() { + // S s(5); + // return s.x; + // } + + // constexpr auto x = f(); + public void testConstexprConstructorConstructorBody() throws Exception { + assertEvaluationEquals(26); + } + + // struct S { + // int x; + // constexpr S(int i) : x{i*i} { x++; } + // }; + // constexpr auto f() { + // S s = S(5); + // return s.x; + // } + + // constexpr auto x = f(); + public void testConstexprConstructorCopyConstruction() throws Exception { + assertEvaluationEquals(26); + } + + // struct S { + // int x; + // constexpr S(int i) : x{i*i} { x++; } + // }; + // constexpr auto f() { + // S s = S(5); + // return s.x; + // } + + // constexpr auto var = f(); + public void testIdempotence() throws Exception { + // Querying a value a second time should produce the same result. + assertEvaluationEquals(26); + assertEvaluationEquals(26); + } + + // struct S { + // int x; + // constexpr S() : x{5} { x++; x++; } + // }; + // constexpr auto f() { + // S s; + // return s.x; + // } + + // constexpr auto x = f(); + public void testConstexprConstructorDefaultConstruction() throws Exception { + assertEvaluationEquals(7); + } + + // struct Base { + // int base_member; + // constexpr Base(int i) : base_member(i) {} + // }; + // struct Derived : Base { + // int derived_member; + // constexpr Derived(int i) : Base(2), derived_member(i) {} + // }; + // constexpr auto f() { + // Derived t(1); + // return t.base_member + t.derived_member; + // } + + // constexpr auto x = f(); + public void testConstexprConstructorInheritance() throws Exception { + assertEvaluationEquals(3); + } + + // struct point { + // int x, y; + // }; + // + // constexpr int f() { + // point p{2,3}; + // return p.y; + // } + + // constexpr int x = f(); + public void testInitializationOfCompositeValues() throws Exception { + assertEvaluationEquals(3); + } + + // struct T { + // constexpr T(int i):x{2*i} {} + // constexpr int get() const { return x; } + // int x; + // }; + // struct S { + // T t{2}; + // }; + // constexpr int f() { + // S s; + // return s.t.get(); + // } + + // constexpr int x = f(); + public void testNestedConstructorCall() throws Exception { + assertEvaluationEquals(4); + } + + // struct S { + // constexpr int get() const { + // return x + y; + // } + // private: + // int x = 2; + // int y = 4; + // }; + // constexpr int f(S s) { + // return s.get(); + // } + + // constexpr int x = f(S{}); + public void testImplicitConstructorOfLiteralTypeWithImplicitDestructorIsConstexpr() throws Exception { + assertEvaluationEquals(6); + } + + // struct S { + // constexpr int get() const { + // return x + y; + // } + // ~S()=default; + // private: + // int x = 2; + // int y = 4; + // }; + // constexpr int f(S s) { + // return s.get(); + // } + + // constexpr int x = f(S{}); + public void testImplicitConstructorOfLiteralTypeWithDefaultedDestructorIsConstexpr() throws Exception { + assertEvaluationEquals(6); + } + + // struct S { + // constexpr int get() const { + // return x + y; + // } + // ~S() {} + // private: + // int x = 2; + // int y = 4; + // }; + // constexpr int f(S s) { + // return s.get(); + // } + + // constexpr int x = f(S{}); + public void testImplicitConstructorOfLiteralTypeWithUserDefinedDestructorIsNotConstexpr() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // struct S { + // int x = 2; + // int y = 4; + // }; + // constexpr int f(S s) { + // return s.x; + // } + + // constexpr int x = f(S{}); + public void testImplicitConstructorOfAggregateTypeIsConstexpr() throws Exception { + assertEvaluationEquals(2); + } + + // struct S { + // S() {} + // int x = 2; + // int y = 4; + // }; + // constexpr int f(S s) { + // return s.x; + // } + + // constexpr int x = f(S{}); + public void testUserDefinedDefaultConstructorIsNotConstexpr() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // struct S { + // constexpr S(int x):x{x+1} { + // } + // int x; + // }; + // constexpr int f() { + // S s(5); + // return s.x; + // } + + // constexpr int x = f(); + public void testCtorCall() throws Exception { + assertEvaluationEquals(6); + } + + // struct S { + // constexpr S(int x):x{x} { + // } + // int x; + // }; + // + // constexpr int f() { + // S s1{5}; + // S s2{s1.x * 10}; + // s1.x = 10; + // return s2.x; + // } + + // constexpr int x = f(); + public void testArgumentEvaluation() throws Exception { + assertEvaluationEquals(50); + } + + // struct B { + // int x, y; + // }; + // struct A { + // int m, n, k; + // B b; + // }; + // constexpr int f() { + // A a{1, 2, 3, { 4, 5 } }; + // return a.b.y; + // } + + // constexpr int x = f(); + public void testInitializationOfNestedCompositeValues() throws Exception { + assertEvaluationEquals(5); + } + + // struct point { + // int x, y; + // }; + // + // constexpr int f() { + // point p{2,3}; + // p.x = p.y * p.y; // 3 * 3 + // return p.x; + // } + + // constexpr int x = f(); + public void testAssignmentOfCompositeValues() throws Exception { + assertEvaluationEquals(9); + } + + // struct B { + // int x, y; + // }; + // struct A { + // int m, n, k; + // B b; + // }; + // + // constexpr int f() { + // A a{1, 2, 3, { 4, 5 } }; + // a.b.y = a.k + a.b.x; // 3 + 4 + // return a.b.y; + // } + + // constexpr int x = f(); + public void testAssignmentOfNestedCompositeValues() throws Exception { + assertEvaluationEquals(7); + } + + // struct S { + // int x = 1, y = 3; + // }; + // constexpr auto f() { + // S s; + // s.x++; + // return s.x; + // } + + // constexpr auto x = f(); + public void testStructDefaultInitialization() throws Exception { + assertEvaluationEquals(2); + } + + // struct S { + // int x = 1, y = 3; + // }; + // constexpr auto f() { + // S s{5, 7}; + // s.x++; + // return s.x; + // } + + // constexpr auto x = f(); + public void testStructDefaultInitializationOverride() throws Exception { + assertEvaluationEquals(6); + } + + // struct T { + // int a = 7; + // }; + // struct S { + // int x = 1; + // T t; + // }; + // constexpr auto f() { + // S s; + // s.t.a++; + // return s.t.a; + // } + + // constexpr auto x = f(); + public void testNestedStructDefaultInitialization() throws Exception { + assertEvaluationEquals(8); + } + + // struct S { + // constexpr S(int x, int y):x{x}, y{y*2} {} + // constexpr int getY() const { + // return y; + // } + // private: + // int x; + // int y; + // }; + // constexpr S f() { + // return S{3, 5}; + // } + + // constexpr int x = f().getY(); + public void testSimpleTypeConstructorExpression2() throws Exception { + assertEvaluationEquals(10); + } + + // struct S { + // int x, y; + // }; + // constexpr S s{1,5}; + + // constexpr int x = s.y; + public void testInitialValueOfComposite() throws Exception { + assertEvaluationEquals(5); + } + + // struct Point { + // constexpr Point(int x, int y):x{x}, y{y*2} { + // } + // int x, y; + // }; + // constexpr int f() { + // Point p{5, 6}; + // return p.y; + // } + + // constexpr int x = f(); + public void testCtorInitializerList() throws Exception { + assertEvaluationEquals(12); + } + + // struct Point { + // constexpr Point(int x, int y):x{x}, y{y*2} { + // } + // int x, y; + // }; + // constexpr int f() { + // Point p(5, 6); + // return p.y; + // } + + // constexpr int x = f(); + public void testCtorConstructorInitializer() throws Exception { + assertEvaluationEquals(12); + } + + // struct Point { + // constexpr Point(int x, int y):x{x}, y{y*2} { + // } + // int x, y; + // }; + // constexpr int f() { + // Point p = {5, 6}; + // return p.y; + // } + + // constexpr int x = f(); + public void testCtorEqualsInitializer() throws Exception { + assertEvaluationEquals(12); + } + + // struct S { + // constexpr S(int x):x{x*2} { + // } + // int x; + // }; + // constexpr int f() { + // S s = 6; + // return s.x; + // } + + // constexpr int x = f(); + public void testCtorImplicitConversion() throws Exception { + assertEvaluationEquals(12); + } + + // struct Point { + // constexpr Point(int x, int y):x{x}, y{y*2} { + // } + // int x, y; + // }; + // constexpr int f() { + // Point p1{5, 6}; + // Point p2 = p1; + // return p2.y; + // } + + // constexpr int x = f(); + public void testCtorLvalueCopyConstruction() throws Exception { + assertEvaluationEquals(12); + } + + // struct Point { + // constexpr Point(int x, int y):x{x}, y{y*2} { + // } + // int x, y; + // }; + // constexpr int f() { + // Point p = Point{5, 6}; + // return p.y; + // } + + // constexpr int x = f(); + public void testCtorRvalueCopyConstruction() throws Exception { + assertEvaluationEquals(12); + } + + // struct T { + // int y = 7, z = 11; + // }; + // struct S { + // int x = 1; + // T t{8, 12}; + // }; + // constexpr auto f() { + // S s; + // s.t.y++; + // s.t.z++; + // return s.t.y + s.t.z; + // } + + // constexpr auto x = f(); + public void testNestedStructDefaultInitializationOverride() throws Exception { + assertEvaluationEquals(22); + } + + // struct T { + // int member; + // constexpr T(int i) : member(i) {} + // }; + + // constexpr auto x = T(2).member; + public void testFundamentalTypeDirectInitializationWithParenthesis() throws Exception { + assertEvaluationEquals(2); + } + + // struct Base { + // int x = 5; + // }; + // struct Derived : Base { + // int y = 10; + // }; + // constexpr int f() { + // Derived d{}; + // return d.x; + // } + + // constexpr int x = f(); + public void testInheritedMemberVariable1() throws Exception { + assertEvaluationEquals(5); + } + + // struct X { + // constexpr X(int y):y{2*y} {} + // int y; + // }; + // struct Base { + // X x{5}; + // }; + // struct Derived : Base { + // int n = 2 * x.y; + // }; + // constexpr int f() { + // Derived d{}; + // return d.n; + // } + + // constexpr int x = f(); + public void testInheritedMemberVariable2() throws Exception { + assertEvaluationEquals(20); + } + + // struct S { + // constexpr S(int x):x{x} { + // } + // int x; + // int y{2 * x}; + // }; + // constexpr int f() { + // S s{5}; + // return s.y; + // } + + // constexpr int x = f(); + public void testOrderOfFieldInitialization() throws Exception { + assertEvaluationEquals(10); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/DoWhileStatementTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/DoWhileStatementTests.java new file mode 100644 index 00000000000..d1bc0c30a74 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/DoWhileStatementTests.java @@ -0,0 +1,92 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; + +import junit.framework.TestSuite; + +public class DoWhileStatementTests extends TestBase { + public static class NonIndexing extends DoWhileStatementTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends DoWhileStatementTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int f(int n) { + // int sum { 0 }; + // int i { 0 }; + // do { + // sum += i; + // i++; + // } while (i <= n); + // return sum; + // } + + // constexpr int x = f(10); + public void testDoWhile() throws Exception { + assertEvaluationEquals(55); + } + + // constexpr int f() { + // int sum { 0 }; + // do { + // sum++; + // } while (true); + // return sum; + // } + + // constexpr int x = f(); + public void testDoWhileInfiniteLoop() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f() { + // int sum { 0 }; + // do { + // return 42; + // } while (true); + // return sum; + // } + + // constexpr int x = f(); + public void testDoWhileReturn() throws Exception { + assertEvaluationEquals(42); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // do + // --n, ++sum; + // while(n > 0); + // return sum; + // } + + // constexpr int x = f(10); + public void testDoWhileWithNonCompoundBodyStatement() throws Exception { + assertEvaluationEquals(10); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // do + // return 42; + // while(n > 0); + // return sum; + // } + + // constexpr int x = f(10); + public void testDoWhileWithReturnInNonCompoundBodyStatement() throws Exception { + assertEvaluationEquals(42); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/FloatingPointValueTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/FloatingPointValueTests.java new file mode 100644 index 00000000000..100aa488a54 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/FloatingPointValueTests.java @@ -0,0 +1,111 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class FloatingPointValueTests extends TestBase { + public static class NonIndexing extends FloatingPointValueTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends FloatingPointValueTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr auto x = 2.5; + public void testDoubleLiteral() throws Exception { + assertEvaluationEquals(2.5); + } + + // constexpr auto x = .5f; + public void testFloatLiteral() throws Exception { + assertEvaluationEquals(0.5); + } + + // constexpr auto x = 2.l; + public void testLongDoubleLiteral() throws Exception { + assertEvaluationEquals(2.0); + } + + // constexpr auto x = 123.456e-67; + public void testDoubleLiteralWithScientificNotation() throws Exception { + assertEvaluationEquals(123.456e-67); + } + + // constexpr auto x = .1E4f; + public void testFloatLiteralWithScientificNotation() throws Exception { + assertEvaluationEquals(.1E4f); + } + + // constexpr double f() { + // double x = 5.5; + // double y = 2.1; + // return x * 4 + y / 3; + // } + + // constexpr double x = f(); + public void testBinaryOperationsWithFloatingPointNumbers() throws Exception { + assertEvaluationEquals(22.7); + } + + // constexpr bool f() { + // double x = 5.0; + // int y = 5; + // return x == y; + // } + + // constexpr bool x = f(); + public void testComparisonBetweenFloatingPointValueAndIntegralValue1() throws Exception { + assertEvaluationEquals(true); + } + + // constexpr bool f() { + // double x = 5.1; + // int y = 5; + // return x == y; + // } + + // constexpr bool x = f(); + public void testComparisonBetweenFloatingPointValueAndIntegralValue2() throws Exception { + assertEvaluationEquals(false); + } + + // constexpr auto x = float{} + float(); + public void testFloatDefaultValue() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto f() { + // float x{}; + // return x; + // } + + // constexpr auto x = f(); + public void testFloatValueInitialization() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto x = double{} + double(); + public void testDoubleDefaultValue() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto f() { + // double x{}; + // return x; + // } + + // constexpr auto x = f(); + public void testDoubleValueInitialization() throws Exception { + assertEvaluationEquals(0); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ForStatementTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ForStatementTests.java new file mode 100644 index 00000000000..d62b0621f4e --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ForStatementTests.java @@ -0,0 +1,207 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; + +import junit.framework.TestSuite; + +public class ForStatementTests extends TestBase { + public static class NonIndexing extends ForStatementTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends ForStatementTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int f(int n) { + // int sum { 0 }; + // for (int i = 0; i <= n; i++) { + // sum += i; + // } + // return sum; + // } + + // constexpr int x = f(10); + public void testSimpleIndexBasedForLoop() throws Exception { + assertEvaluationEquals(55); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // for (int i = 0; i <= n; i++) { + // sum += i; + // return 42; + // } + // return sum; + // } + + // constexpr int x = f(10); + public void testReturnInIndexBasedForLoop() throws Exception { + assertEvaluationEquals(42); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // for (int i = 0; true; i++) { + // sum += i; + // } + // return sum; + // } + + // constexpr int x = f(10); + public void testInfiniteLoopInIndexBasedForLoop() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // int i { 0 }; + // for (; i < n; i++) { + // sum += i; + // } + // return sum; + // } + + // constexpr int x = f(10); + public void testIndexBasedForLoopWithEmptyInitializationStatement() throws Exception { + assertEvaluationEquals(45); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // for (int i = 0; i < n;) { + // sum += i++; + // } + // return sum; + // } + + // constexpr int x = f(10); + public void testIndexBasedForLoopWithEmptyIterationSequence() throws Exception { + assertEvaluationEquals(45); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // for (int i = 0; i <= n; i++) + // sum += i; + // return sum; + // } + + // constexpr int x = f(10); + public void testIndexBasedForLoopWithNonCompoundBodyStatement() throws Exception { + assertEvaluationEquals(55); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // for (int i = 0; i <= n; i++) + // return 42; + // return sum; + // } + + // constexpr int x = f(10); + public void testIndexBasedForLoopWithReturnInNonCompoundBodyStatement() throws Exception { + assertEvaluationEquals(42); + } + + // constexpr int f() { + // int sum = 0; + // for(int i = 0; i < 10; ++i) { + // sum++; + // continue; + // sum++; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testIndexBasedForLoopWithContinueStatement() throws Exception { + assertEvaluationEquals(10); + } + + // constexpr int f() { + // int sum = 0; + // int arr[] = {1,2,3,4,5,6,7,8,9,10}; + // for(int i = 0; i < 10; ++i) { + // if(i % 2 == 0) { + // continue; + // } + // sum += arr[i]; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testIndexBasedForLoopWithNestedContinueStatement() throws Exception { + assertEvaluationEquals(30); + } + + // constexpr int f() { + // int sum = 0; + // int arr[] = {1,2,3,4,5,6,7,8,9,10}; + // for(int i = 0; i < 10; ++i) { + // if(i == 5) { + // break; + // } + // sum += arr[i]; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testIndexBasedForLoopWithNestedBreakStatement() throws Exception { + assertEvaluationEquals(15); + } + + // constexpr int triple(int x) { + // return x * 3; + // } + // constexpr int f() { + // int sum = 0; + // for(int y = 4; int x = triple(y); y--) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testDeclarationInForStatementCondition1() throws Exception { + assertEvaluationEquals(30); + } + + // constexpr int f() { + // int count = 0; + // for(;;) { + // if(count++ > 10) { + // break; + // } + // } + // return count; + // } + + // constexpr int x = f(); + public void testInfiniteForLoop() throws Exception { + assertEvaluationEquals(12); + } + + // constexpr int fac(int n) { + // int result = 1; + // for(int i = 1; i <= n; result *= i++); + // return result; + // } + + // constexpr int x = fac(5); + public void testForLoopWithNullStatementAsBody() throws Exception { + assertEvaluationEquals(120); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/FunctionTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/FunctionTemplateTests.java new file mode 100644 index 00000000000..21286f972fe --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/FunctionTemplateTests.java @@ -0,0 +1,375 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class FunctionTemplateTests extends TestBase { + public static class NonIndexing extends FunctionTemplateTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends FunctionTemplateTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // template + // constexpr T add(T a, T b) { + // return a + b; + // } + + // constexpr auto x = add(5.5, 6.3); + public void testImplicitTemplateInstantiation() throws Exception { + assertEvaluationEquals(11.8); + } + + // class Integer { + // int i; + // public: + // constexpr Integer(int i):i{i} {} + // constexpr int get() const { return i; } + // }; + // template + // constexpr int f() { + // T t{10}; + // return t.get(); + // } + + // constexpr int x = f(); + public void testExplicitTemplateInstantiation() throws Exception { + assertEvaluationEquals(10); + } + + // template + // constexpr int f() { + // int result = I * 4; + // return result; + // } + + // constexpr int x = f<5>(); + public void testTemplateWithNonTypeTemplateParameter() throws Exception { + assertEvaluationEquals(20); + } + + // template + // constexpr T sum(T v) { + // return v; + // } + // template + // constexpr T sum(T first, Args... args) { + // return first + sum(args...); + // } + + // constexpr int x = sum(1,2,3,4,5); + public void testVariadicTemplate() throws Exception { + assertEvaluationEquals(15); + } + + // template + // constexpr int count(Args... args) { + // return sizeof...(args); + // } + + // constexpr int x = count(1,2,3,4,5); + public void testParameterPackSizeof() throws Exception { + assertEvaluationEquals(5); + } + + // class Integer { + // int i; + // public: + // constexpr Integer(int i):i{i} {} + // constexpr int get() const { return i; } + // constexpr bool operator<=(Integer const& rhs) const { return i <= rhs.i; } + // constexpr Integer& operator++() { ++i; return *this; } + // constexpr Integer& operator*=(Integer const& rhs) { i *= rhs.i; return *this; } + // }; + // + // template + // constexpr int fac(T n) { + // T total{1}; + // for(T i{1}; i <= n; ++i) { + // total *= i; + // } + // return total.get(); + // } + + // constexpr int x = fac(Integer{5}); + public void testTemplateInstantiationOfForLoop() throws Exception { + assertEvaluationEquals(120); + } + + // class Integer { + // int i; + // public: + // constexpr Integer(int i):i{i} {} + // constexpr int get() const { return i; } + // constexpr bool operator<=(Integer const& rhs) const { return i <= rhs.i; } + // constexpr Integer& operator++() { ++i; return *this; } + // constexpr Integer& operator+=(Integer const& rhs) { i += rhs.i; return *this; } + // }; + // template + // constexpr int f(T n) { + // T sum { 0 }; + // T i { 0 }; + // do { + // sum += i; + // ++i; + // } while (i <= n); + // return sum.get(); + // } + + // constexpr int x = f(Integer{10}); + public void testTemplateInstantiationOfDoWhileLoop() throws Exception { + assertEvaluationEquals(55); + } + + // template + // constexpr T add(T a, T b) { + // ; + // return a + b; + // } + + // constexpr auto x = add(5.5, 6.3); + public void testNullStatementInFunctionTemplate() throws Exception { + assertEvaluationEquals(11.8); + } + + // class Integer { + // int i; + // public: + // constexpr Integer(int i):i{i} {} + // constexpr int get() const { return i; } + // constexpr bool operator<=(Integer const& rhs) const { return i <= rhs.i; } + // constexpr Integer& operator++() { ++i; return *this; } + // constexpr Integer& operator*=(Integer const& rhs) { i *= rhs.i; return *this; } + // }; + // + // template + // constexpr int fac(T n) { + // T total{1}; + // T i{1}; + // while(i <= n) { + // total *= i; + // ++i; + // } + // return total.get(); + // } + + // constexpr int x = fac(Integer{5}); + public void testTemplateInstantiationOfWhileLoop() throws Exception { + assertEvaluationEquals(120); + } + + // template + // constexpr T div(T a, T b) { + // if(b > 0) { + // return a / b; + // } + // return -1; + // } + + // constexpr auto x = div(11.5, 2.0); + public void testTemplateInstantiationOfIfStatement() throws Exception { + assertEvaluationEquals(5.75); + } + + // constexpr int count(int first) { return 1; } + // constexpr int count(double first) { return 4; } + // template + // constexpr int count(T first, Args... args) { + // return count(first) + count(args...); + // } + + // constexpr int x = count(1, 0.5, 3.4, 5, 2.2); + public void testVariadicTemplateWithVaryingTypes() throws Exception { + assertEvaluationEquals(14); + } + + // template + // constexpr int sum(Args... args) { + // int sum = 0; + // for(auto x : {args...}) { + // sum += x; + // } + // return sum; + // } + + // constexpr long long x = sum(1,2,3,4,5); + public void testExpansionOfVariadicTemplateParameterIntoInitializerList() throws Exception { + assertEvaluationEquals(15); + } + + // template + // constexpr int sum(Args... args) { + // int sum = 0; + // for(auto x : {(args*2)...}) { + // sum += x; + // } + // return sum; + // } + + // constexpr long long x = sum(1,2,3,4,5); + public void testExpressionInVariadicTemplateParameterExpansion1() throws Exception { + assertEvaluationEquals(30); + } + + // template + // constexpr int sumOfPrimes(Indices... indices) { + // // all prime numbers below 100 + // int primes[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97}; + // int sum = 0; + // for(int prime : {primes[indices]...}) { + // sum += prime; + // } + // return sum; + // } + + // constexpr int x = sumOfPrimes(0, 4, 9, 11, 19); + public void testExpressionInVariadicTemplateParameterExpansion2() throws Exception { + assertEvaluationEquals(150); + } + + // template + // class index_sequence{}; + // + // template + // constexpr int sumOfPrimes(index_sequence) { + // // all prime numbers below 100 + // int primes[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97}; + // int sum = 0; + // for(int prime : {primes[indices]...}) { + // sum += prime; + // } + // return sum; + // } + + // constexpr int x = sumOfPrimes(index_sequence<0, 4, 9, 11, 19>{}); + public void testIndexSequence1() throws Exception { + assertEvaluationEquals(150); + } + + // template + // constexpr int getArrayLength(T(&)[size]){ + // return size; + // } + // constexpr int f() { + // int arr[10]{}; + // return getArrayLength(arr); + // } + + // constexpr int x = f(); + public void testFunctionTemplateWithArrayParameter1() throws Exception { + assertEvaluationEquals(10); + } + + // template + // constexpr void doubleArrayContents(T(&arr)[size]) { + // for(int i = 0; i < size; i++) { + // arr[i] *= 2; + // } + // } + // constexpr int f() { + // int arr[]{1,2,3,4,5}; + // doubleArrayContents(arr); + // return arr[3]; + // } + + // constexpr int x = f(); + public void testFunctionTemplateWithArrayParameter2() throws Exception { + assertEvaluationEquals(8); + } + + // struct S { + // constexpr S(int n):x{n*2} {} + // constexpr int get() { return x; } + // private: + // int x; + // }; + // template + // constexpr int f() { + // S s{N}; + // return s.get(); + // } + + // constexpr int x = f<10>(); + public void testInstantiationOfConstructorInFunctionTemplate1() throws Exception { + assertEvaluationEquals(20); + } + + // struct Number { + // constexpr Number(int):isFP{false} {} + // constexpr Number(double):isFP{true} {} + // constexpr bool isFloatingPoint() { return isFP; } + // private: + // bool isFP; + // }; + // template + // constexpr bool f() { + // Number n{T{}}; + // return n.isFloatingPoint(); + // } + // constexpr bool x = f(); + public void testInstantiationOfConstructorInFunctionTemplate2() throws Exception { + assertEvaluationEquals(true); + } + + // template + // struct Adder { + // constexpr int sum() { + // return A + B; + // } + // }; + // template + // constexpr int f() { + // switch(Adder{}.sum()) { + // case 10: + // return 1; + // case 11: + // return 2; + // case 12: + // return 3; + // default: + // return 4; + // } + // } + + // constexpr int x = f<9,2>(); + public void testInstantiationOfSwitchStatement() throws Exception { + assertEvaluationEquals(2); + } + + // template + // constexpr int f() { + // typedef T myType; + // myType x = 5; + // x *= 5; + // return x; + // } + + // constexpr int x = f(); + public void testInstantiationOfTypedefDeclaration() throws Exception { + assertEvaluationEquals(25); + } + + // template + // constexpr int f() { + // using myint = T; + // myint x = 5; + // x *= 5; + // return x; + // } + + // constexpr int x = f(); + public void testInstantiationOfAliasDeclaration() throws Exception { + assertEvaluationEquals(25); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/FunctionTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/FunctionTests.java new file mode 100644 index 00000000000..e76e9c8697b --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/FunctionTests.java @@ -0,0 +1,248 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; + +import junit.framework.TestSuite; + +public class FunctionTests extends TestBase { + public static class NonIndexing extends FunctionTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends FunctionTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // struct S { + // int x; + // }; + // constexpr int g(S const& s) { + // return s.x; + // } + // constexpr int f() { + // S s{5}; + // return g(s); + // } + + // constexpr int x = f(); + public void testAccessMemberOfCompositeParameter() throws Exception { + assertEvaluationEquals(5); + } + + // constexpr int function(int n) { return n > 0 ? n + function(n-1) : n; } + + // constexpr int x = function(10); + public void testRecursion() throws Exception { + assertEvaluationEquals(55); + } + + // constexpr int helper(int n) { + // int m = 5; + // return m + n; + // } + // constexpr int function() { + // int value = helper(5); + // return value + helper(5); + // } + + // constexpr int x = function(); + public void testEvaluationOfConstexprFunctionCalls() throws Exception { + assertEvaluationEquals(20); + } + + // constexpr int g(int i) { + // i++; + // return i; + // } + // + // constexpr auto f() { + // int a = 3; + // int b = g(a); + // b++; + // return a; + // } + + // constexpr auto x = f(); + public void testFunctionReturnValueIsCopiedAndNotReferenced() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr void incr(int x) { + // x = x + 1; + // } + // constexpr int f() { + // int a { 5 }; + // incr(a); + // return a; + // } + + // constexpr auto x = f(); + public void testPassingIntByValue() throws Exception { + assertEvaluationEquals(5); + } + + // constexpr void incr(int &x) { + // x++; + // } + // constexpr int f() { + // int a { 5 }; + // incr(a); + // return a; + // } + + // constexpr auto x = f(); + public void testPassingIntByReference1() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr void incr(int &x, int &y) { + // x++; + // y++; + // } + // constexpr int f() { + // int a { 5 }; + // incr(a, a); + // return a; + // } + + // constexpr auto x = f(); + public void testPassingIntByReference2() throws Exception { + assertEvaluationEquals(7); + } + + // struct S { + // int x; + // }; + // constexpr void g(S s) { + // s.x++; + // } + // constexpr int f() { + // S s{5}; + // g(s); + // return s.x; + // } + + // constexpr int x = f(); + public void testPassingCompositeByValue() throws Exception { + assertEvaluationEquals(5); + } + + // struct Point { int x, y; }; + // constexpr void incr(Point &point) { + // point.x++; + // } + // constexpr int f() { + // Point p{ 2, 4 }; + // incr(p); + // return p.x; + // } + + // constexpr auto x = f(); + public void testPassingCompositeByReference() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int a[2][2] { { 1, 2 }, { 3, 4 } }; + // constexpr int const * g() { + // return a[0]; + // } + // constexpr int f() { + // return g()[1]; + // } + + // constexpr auto x = f(); + public void testPointerReturnValue() throws Exception { + assertEvaluationEquals(2); + } + + // int const y { 5 }; + // constexpr int const & g() { + // return y; + // } + // constexpr int f() { + // return g() + 1; + // } + + // constexpr auto x = f(); + public void testReferenceReturnValue() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr void side_effect(int array[], int length) { + // for (int i = 0; i < length; ++i) { + // array[i]++; + // } + // } + // constexpr int f() { + // int array[4] { 1, 2, 3, 4 }; + // side_effect(array, 4); + // return array[0]; + // } + + // constexpr auto x = f(); + public void testSideEffectsOnArrayParameter() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr int f(int a) { + // { + // int a = 5; + // return a; + // } + // return a; + // } + + // constexpr int x = f(10); + public void testBlockScopeValueLookup1() throws Exception { + assertEvaluationEquals(5); + } + + // constexpr int f(int a) { + // { + // int a = 5; + // } + // return a; + // } + + // constexpr int x = f(10); + public void testBlockScopeValueLookup2() throws Exception { + assertEvaluationEquals(10); + } + + // char foo(); + // constexpr int almost = sizeof(foo()); + + // constexpr int x = almost; + public void testSizeofCallToRegularFunction() throws Exception { + assertEvaluationEquals(1); + } + + // int f() { + // return 5; + // } + + // int x = f(); + public void testNonConstexprFunctionDoesntStoreBodyExecution() throws Exception { + IASTInitializerClause clause = getLastDeclarationInitializer(); + IASTFunctionCallExpression funcExpr = (IASTFunctionCallExpression)clause; + IASTIdExpression idExpr = (IASTIdExpression)funcExpr.getFunctionNameExpression(); + ICPPFunction function = (ICPPFunction)idExpr.getName().resolveBinding(); + ICPPExecution bodyExec = CPPFunction.getFunctionBodyExecution(function, clause); + assertNull(bodyExec); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/IfStatementTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/IfStatementTests.java new file mode 100644 index 00000000000..c6e3a297111 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/IfStatementTests.java @@ -0,0 +1,197 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class IfStatementTests extends TestBase { + public static class NonIndexing extends IfStatementTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends IfStatementTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int f() { + // if (true) { + // return 1; + // } + // return 0; + // } + + // constexpr int x = f(); + public void testSimpleIfTrueBranch() throws Exception { + assertEvaluationEquals(1); + } + + // constexpr int f() { + // if (false) { + // return 1; + // } + // return 0; + // } + + // constexpr int x = f(); + public void testSimpleIfFalseBranch() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr int f() { + // if (true) { + // return 1; + // } else { + // return 0; + // } + // } + + // constexpr int x = f(); + public void testIfElseTrueBranch() throws Exception { + assertEvaluationEquals(1); + } + + // constexpr int f() { + // if (false) { + // return 1; + // } else { + // return 0; + // } + // } + + // constexpr int x = f(); + public void testSimpleIfElseFalseBranch() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr int f() { + // if (false) { + // return 1; + // } else if (true) { + // return 2; + // } else { + // return 0; + // } + // } + + // constexpr int x = f(); + public void testNestedIfTrueBranch() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr int f() { + // if (false) { + // return 1; + // } else if (false) { + // return 2; + // } else { + // return 0; + // } + // } + + // constexpr int x = f(); + public void testNestedIfFalseBranch() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr int f() { + // if (true) + // return 1; + // return 0; + // } + + // constexpr int x = f(); + public void testIfStatementWithNonCompoundThenClause() throws Exception { + assertEvaluationEquals(1); + } + + // constexpr int f() { + // if (false) + // return 1; + // else + // return 0; + // } + + // constexpr int x = f(); + public void testIfStatementWithNonCompoundElseClause() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr int f() { + // int i; + // if (true) { + // i = 10; + // } else { + // i = 20; + // } + // return i; + // } + + // constexpr int x = f(); + public void testIfStatementWithNonReturnClauses() throws Exception { + assertEvaluationEquals(10); + } + + // constexpr int f() { + // int i; + // if (false) + // i = 10; + // else + // i = 20; + // return i; + // } + + // constexpr int x = f(); + public void testIfStatementWithNonReturnClausesAndNonCompoundElseClause() throws Exception { + assertEvaluationEquals(20); + } + + // constexpr int f(int y) { + // if(int x = y*2) { + // return 14 / x; + // } else { + // return 0; + // } + // } + + // constexpr int x = f(1); + public void testDeclarationInIfStatementCondition1() throws Exception { + assertEvaluationEquals(7); + } + + // constexpr int f(int y) { + // if(int x = y*2) { + // return 14 / x; + // } else { + // return 0; + // } + // } + + // constexpr int x = f(0); + public void testDeclarationInIfStatementCondition2() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr int g(int x) { + // return x * 2; + // } + // constexpr int f(int y) { + // if(int x = g(y)) { + // return 14 / x; + // } else { + // return 0; + // } + // } + + // constexpr int x = f(1); + public void testDeclarationInIfStatementCondition3() throws Exception { + assertEvaluationEquals(7); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/IntegralValueTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/IntegralValueTests.java new file mode 100644 index 00000000000..d9213e3edcd --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/IntegralValueTests.java @@ -0,0 +1,259 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; + +import junit.framework.TestSuite; + +public class IntegralValueTests extends TestBase { + public static class NonIndexing extends IntegralValueTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends IntegralValueTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr auto x = int{} + int(); + public void testIntDefaultValue() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto f() { + // int x{}; + // return x; + // } + + // constexpr auto x = f(); + public void testIntValueInitialization() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto x = long{} + long(); + public void testLongDefaultValue() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto f() { + // long x{}; + // return x; + // } + + // constexpr auto x = f(); + public void testLongValueInitialization() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto x = short{} + short(); + public void testShortDefaultValue() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto f() { + // short x{}; + // return x; + // } + + // constexpr auto x = f(); + public void testShortValueInitialization() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto x = bool{} + bool(); + public void testBooleanDefaulValue() throws Exception { + assertEvaluationEquals(false); + } + + // constexpr auto f() { + // bool x{}; + // return x; + // } + + // constexpr auto x = f(); + public void testBoolValueInitialization() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto x = char{} + char(); + public void testCharDefaultValue() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr auto f() { + // char x{'c'}; + // return x; + // } + + // constexpr auto x = f(); + public void testCharValueInitialization() throws Exception { + assertEvaluationEquals('c'); + } + + // constexpr int mul(int op1, int op2) { + // int result = op1 * op2; + // return result; + // } + + // constexpr int x = mul(2, 5); + public void testDeclarationWithEqualsInitializerInSequence() throws Exception { + assertEvaluationEquals(10); + } + + // constexpr int mul(int op1, int op2) { + // int intermediate1 { op1 }; + // int intermediate2 { op2 }; + // return intermediate1 * intermediate2; + // } + + // constexpr int x = mul(2, 5); + public void testDeclarationWithDefaultInitializationInSequence() throws Exception { + assertEvaluationEquals(10); + } + + // constexpr int f() { + // int i(5); + // i++; + // return i; + // } + + // constexpr int x = f(); + public void testDirectInitializationOnFundamentalTypes() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr int f() { + // int invalid; + // return invalid; + // } + + // constexpr int x = f(); + public void testUseOfUninitializedVariableIsError() throws Exception { + assertEvaluationEquals(IntegralValue.UNKNOWN); + } + + // constexpr auto f() { + // int x = 1, y = 1, z = 1; + // return x + y + z; + // } + + // constexpr auto x = f(); + public void testDeclarationWithMultipleDeclarators() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int f() { + // int i{5}; + // i++; + // return i; + // } + + // constexpr int x = f(); + public void testSimpleTypeConstructionInitializerList() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr int f() { + // int i(5); + // i++; + // return i; + // } + + // constexpr int x = f(); + public void testSimpleTypeConstructionConstructorInitializer() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr int f() { + // int i = 5; + // i++; + // return i; + // } + + // constexpr int x = f(); + public void testSimpleTypeConstructionEqualsInitializer1() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr int f() { + // int i = {5}; + // i++; + // return i; + // } + + // constexpr int x = f(); + public void testSimpleTypeConstructionEqualsInitializer2() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr int f() { + // int a { 3 }; + // int b = a; + // b++; + // return a + b; + // } + + // constexpr int x = f(); + public void testCopyInitialization() throws Exception { + assertEvaluationEquals(7); + } + + // constexpr int f() { + // int y = 0, x = 5; + // x++; + // return x; + // } + + // constexpr auto x = f(); + public void testMultipleDeclaratorsInOneDeclaration() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr int f() { + // return int{5}; + // } + + // constexpr int x = f(); + public void testSimpleTypeConstructorExpression1() throws Exception { + assertEvaluationEquals(5); + } + + // constexpr int f() { + // int a { 1 }; // declaration + // a = ++a * ++a; // assignment / side effects + // return a; // returns 6 + // } + + // constexpr auto x = f(); + public void testSideEffects2() throws Exception { + assertEvaluationEquals(6); + } + + // constexpr int x = 2; + + // constexpr int y = x * 4; + public void testAccessGlobalVariableFromGlobalConstexpr() throws Exception { + assertEvaluationEquals(8); + } + + // constexpr int x = 2; + // constexpr int f() { return x * 4; } + + // constexpr int y = f(); + public void testAccessGlobalVariableFromConstexprFunction() throws Exception { + assertEvaluationEquals(8); + } + + // constexpr int x = 0x2a; + public void testHexLiteral() throws Exception { + assertEvaluationEquals(42); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/MemberFunctionTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/MemberFunctionTests.java new file mode 100644 index 00000000000..c9716b384f5 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/MemberFunctionTests.java @@ -0,0 +1,184 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class MemberFunctionTests extends TestBase { + public static class NonIndexing extends MemberFunctionTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends MemberFunctionTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // struct S { + // int x, y; + // constexpr int member() { + // return 4; + // } + // }; + // constexpr int f() { + // S s{3,7}; + // return s.member(); + // } + + // constexpr auto x = f(); + public void testMemberFunctionCall() throws Exception { + assertEvaluationEquals(4); + } + + // struct S { + // int x, y; + // constexpr int member() { + // y++; + // return y; + // } + // }; + // constexpr int f() { + // S s{3,7}; + // return s.member(); + // } + + // constexpr auto x = f(); + public void testMemberFunctionWithImplicitThis() throws Exception { + assertEvaluationEquals(8); + } + + // class Point { + // int x, y; + // public: + // constexpr Point(int x, int y):x{x}, y{y} {} + // constexpr int getY() const; + // }; + // constexpr int Point::getY() const { return y; } + // + // constexpr int f() { + // Point p{4,5}; + // return p.getY(); + // } + + // constexpr int x = f(); + public void testExternallyDefinedMemberFunction() throws Exception { + assertEvaluationEquals(5); + } + + // class S { + // int x; + // public: + // constexpr S(int x):x{x} {} + // constexpr void inc() { x += 30; } + // constexpr int get() const { return x; } + // }; + // + // constexpr int f() { + // S s{20}; + // s.inc(); + // return s.get(); + // } + + // constexpr int x = f(); + public void testPlusEqualsWithinMemberFunction() throws Exception { + assertEvaluationEquals(50); + } + + // class Point { + // int x, y; + // public: + // constexpr Point(int x, int y):x{x}, y{y} {} + // constexpr int getY() const { return this->y; } + // }; + // constexpr int f() { + // Point p{10,40}; + // return p.getY(); + // } + + // constexpr int x = f(); + public void testMemberAccessThroughThisPointer() throws Exception { + assertEvaluationEquals(40); + } + + // struct S { + // int x, y; + // constexpr int member() { + // y = member2(); + // return y; + // } + // constexpr int member2() { + // y++; + // return y; + // } + // }; + // constexpr int f() { + // S s{3,7}; + // return s.member(); + // } + + // constexpr auto x = f(); + public void testNestedMemberFunctionCallsWithImplicitThis() throws Exception { + assertEvaluationEquals(8); + } + + // struct S { + // constexpr S(int x, int y):x{x}, y{y*2} {} + // constexpr int getY() const { + // return y; + // } + // private: + // int x; + // int y; + // }; + // + // constexpr S s{3, 5}; + // constexpr int f() { return s.getY(); } + + // constexpr int x = f(); + public void testGlobalMemberFunctionCallFromConstexprFunction() throws Exception { + assertEvaluationEquals(10); + } + + // struct S { + // constexpr S(int x, int y):x{x}, y{y*2} {} + // constexpr int getY() const { + // return y; + // } + // private: + // int x; + // int y; + // }; + // constexpr S s{3, 5}; + + // constexpr int x = s.getY(); + public void testGlobalMemberFunctionCallFromGlobalConstexpr() throws Exception { + assertEvaluationEquals(10); + } + + // struct S { + // constexpr S(int x, int y):x{x}, y{y} {} + // constexpr int add(S const& other) const { + // return y + other.x * 2; + // } + // private: + // int x, y; + // }; + // + // constexpr int f() { + // S s1{2, 5}; + // S s2{5, 4}; + // return s1.add(s2); + // } + + // constexpr int x = f(); + public void testManualAddMemberFunction() throws Exception { + assertEvaluationEquals(15); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/MemberVariableTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/MemberVariableTests.java new file mode 100644 index 00000000000..8c4c62eb57e --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/MemberVariableTests.java @@ -0,0 +1,117 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class MemberVariableTests extends TestBase { + public static class NonIndexing extends MemberVariableTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends MemberVariableTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // struct Point { int x, y; }; + // constexpr int f() { + // Point p{ 2, 4 }; + // p.x++; + // return p.x; + // } + + // constexpr auto x = f(); + public void testIncrementOnCompositeValues() throws Exception { + assertEvaluationEquals(3); + } + + // struct S { + // int x, y; + // }; + // constexpr int f() { + // const S s{3,7}; + // return s.y; + // } + + // constexpr auto x = f(); + public void testMemberAccessWithConstObject() throws Exception { + assertEvaluationEquals(7); + } + + // struct S { + // int x, y; + // }; + // constexpr S s{5, 6}; + // constexpr int f() { return s.y; } + + // constexpr auto x = f(); + public void testGlobalMemberAccessFromConstexprFunction() throws Exception { + assertEvaluationEquals(6); + } + + // struct S { + // int x, y; + // }; + // constexpr S s{5, 6}; + + // constexpr auto x = s.y; + public void testGlobalMemberAccessFromGlobalConstexpr() throws Exception { + assertEvaluationEquals(6); + } + + // struct T { + // constexpr T(int x):x{2*x}{} + // int x; + // }; + // struct S { + // T t{5}; + // int i = t.x * 2; + // }; + // constexpr int f() { + // S s{}; + // return s.i; + // } + + // constexpr int x = f(); + public void testFieldDependsOnOtherField() throws Exception { + assertEvaluationEquals(20); + } + + // class S { + // int arr[4]{2,4,6,8}; + // public: + // constexpr int *getPtr() { + // return arr; + // } + // }; + // constexpr int f() { + // S s{}; + // int *ptr = s.getPtr()+2; + // return *ptr; + // } + + // constexpr int x = f(); + public void testMemberInitializationWithoutUserDefinedCtor() throws Exception { + assertEvaluationEquals(6); + } + + // struct S { + // static const int x = 5; + // }; + // constexpr int f() { + // return S::x; + // } + + // constexpr int x = f(); + public void testAccessOfStaticField() throws Exception { + assertEvaluationEquals(5); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/PointerTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/PointerTests.java new file mode 100644 index 00000000000..bbc5cc5b6fb --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/PointerTests.java @@ -0,0 +1,355 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; + +import junit.framework.TestSuite; + +public class PointerTests extends TestBase { + public static class NonIndexing extends PointerTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends PointerTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int f() { + // int bar[2] { 3, 7 }; + // int * bar_ptr { bar }; + // bar_ptr++; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerArithmeticsPostFixIncr() throws Exception { + assertEvaluationEquals(7); + } + + // constexpr int f() { + // int bar[2] { 3, 7 }; + // int * bar_ptr { bar }; + // bar_ptr++; + // bar_ptr--; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerArithmeticsPostFixDecr() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int f() { + // int n { 0 }; + // int * nPtr { &n }; + // nPtr++; + // return *nPtr; + // } + + // constexpr int x = f(); + public void testDereferencingOfPointerToInvalidMemoryShouldFail() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar + 2 }; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerArithmeticInDeclaration() throws Exception { + assertEvaluationEquals(7); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar }; + // int * bar_ptr2 { bar + 3 }; + // return bar_ptr2 - bar_ptr; + // } + + // constexpr int x = f(); + public void testSubtractionOfPointersToSameArrayShouldYieldDistance() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar }; + // bar_ptr = bar_ptr + 1; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerAddition() throws Exception { + assertEvaluationEquals(5); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar }; + // bar_ptr += 2; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerAdditionAndAssignment() throws Exception { + assertEvaluationEquals(7); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar + 2}; + // bar_ptr = bar_ptr - 2; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerSubtraction() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar + 2 }; + // bar_ptr -= 2; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerSubtractionAndAssignment() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar }; + // int * bar_ptr2 { bar_ptr }; + // return *bar_ptr2; + // } + + // constexpr int x = f(); + public void testPointerDeclarationFromPointer() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar }; + // int * bar_ptr2 { bar_ptr }; + // bar_ptr++; + // return *bar_ptr2; + // } + + // constexpr int x = f(); + public void testPointersHaveSeparatePositions() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar }; + // int * bar_ptr2 { bar_ptr + 1 }; + // return *bar_ptr2; + // } + + // constexpr int x = f(); + public void testPointerAdditionInDeclaration() throws Exception { + assertEvaluationEquals(5); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar + 3 }; + // int * bar_ptr2 { bar_ptr - 1 }; + // return *bar_ptr2; + // } + + // constexpr int x = f(); + public void testPointerSubtractionInDeclaration() throws Exception { + assertEvaluationEquals(7); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar + 3 }; + // bar_ptr++; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testDereferencingOnePastTheEndPointerIsInvalid() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar + 3 }; + // bar_ptr++; + // bar_ptr--; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testDereferencingIncrementedOnePastTheEndAndThenDecrementedBackInRageAgainPointerIsValid() throws Exception { + assertEvaluationEquals(11); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar + 3 }; + // bar_ptr += 2; + // bar_ptr -= 2; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testDereferencingIncrementedTWOPastTheEndAndThenDecrementedBackInRageAgainPointerIsInvalid() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar }; + // bar_ptr--; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerWithNegativePositionIsInvalid() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar }; + // bar_ptr--; + // bar_ptr++; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerThatOnceHasNegativePositionStaysInvalid() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar + 4 }; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerDeclaredOnePastTheEndIsInvalid() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar + 4 }; + // bar_ptr--; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerDeclaredOnePastTheEndAndThenDecrementedBackInRageAgainIsValid() throws Exception { + assertEvaluationEquals(11); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar + 5 }; + // bar_ptr -= 2; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerDeclaredTwoPastTheEndAndThenDecrementedBackInRageAgainStaysInvalid() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar - 1 }; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerDeclaredWithNegativePositionIsInvalid() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int * bar_ptr { bar - 1 }; + // bar_ptr++; + // return *bar_ptr; + // } + + // constexpr int x = f(); + public void testPointerDelcaredWithNegativePositionStaysInvalid() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f() { + // int a { 1 }; // declaration + // int b { 2 }; + // int * ptr { &a }; + // ptr = &b; + // return *ptr; + // } + + // constexpr auto x = f(); + public void testPointerAssignment() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr auto f() { + // int x { 1 }; + // int * x_ptr { &x }; + // *x_ptr = 2; + // return *x_ptr; + // } + + // constexpr auto x = f(); + public void testPointerValueAssignment() throws Exception { + assertEvaluationEquals(2); + } + + // struct S { + // int x, y; + // }; + // constexpr int f() { + // S s { 1, 2 }; + // int * s_ptr { &s.x }; + // *s_ptr = 3; + // return *s_ptr; + // } + + // constexpr auto x = f(); + public void testPointerToStructMember() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int f() { + // int a { 5 }; + // int * aPtr { &a }; + // (*aPtr)++; + // return a; + // } + + // constexpr auto x = f(); + public void testPointer() throws Exception { + assertEvaluationEquals(6); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/RangeBasedForStatementTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/RangeBasedForStatementTests.java new file mode 100644 index 00000000000..f8c8c428263 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/RangeBasedForStatementTests.java @@ -0,0 +1,399 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; + +import junit.framework.TestSuite; + +public class RangeBasedForStatementTests extends TestBase { + public static class NonIndexing extends RangeBasedForStatementTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends RangeBasedForStatementTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int sum { 0 }; + // for (auto i : bar) { + // sum += i; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testSimpleRangeBasedForLoop() throws Exception { + assertEvaluationEquals(26); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int sum { 0 }; + // for (auto i : bar) { + // return 42; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testReturnInRangeBasedForLoop() throws Exception { + assertEvaluationEquals(42); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int sum { 0 }; + // for (auto& i : bar) { + // i++; + // } + // for (auto i : bar) { + // sum += i; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopReferences() throws Exception { + assertEvaluationEquals(30); + } + + // constexpr void incr(int & i) { + // i++; + // } + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int sum { 0 }; + // for (auto& i : bar) { + // incr(i); + // } + // for (auto i : bar) { + // sum += i; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testPassReferenceObtainedFromRangeBasedForLoopToFunctionAndModify() throws Exception { + assertEvaluationEquals(30); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int sum { 0 }; + // for (auto i : bar) + // sum += i; + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopWithNonCompoundBodyStatement() throws Exception { + assertEvaluationEquals(26); + } + + // constexpr int f() { + // int bar[4] { 3, 5, 7, 11 }; + // int sum { 0 }; + // for (auto i : bar) + // return 42; + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopWithReturnInNonCompoundBodyStatement() throws Exception { + assertEvaluationEquals(42); + } + + // class Range { + // int arr[5]; + // public: + // constexpr Range():arr{1,2,3,4,5} {} + // constexpr const int* begin() const { return arr; } + // constexpr const int* end() const { return arr + 5; } + // }; + // constexpr int f() { + // Range range{}; + // int sum{0}; + // for(int x : range) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopOverCustomType() throws Exception { + assertEvaluationEquals(15); + } + + // class Range { + // int arr[5]; + // public: + // constexpr Range():arr{1,2,3,4,5} {} + // constexpr int* begin() { + // return arr; + // } + // constexpr int* end() { + // return arr + 5; + // } + // }; + // constexpr int f() { + // Range range{}; + // int sum{0}; + // for(int &x : range) { + // x++; + // } + // for(int const& x : range) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopThatModifiesElementsInCustomType() throws Exception { + assertEvaluationEquals(20); + } + + // class Range { + // int arr1[5]; + // int arr2[5]; + // public: + // constexpr Range():arr1{1,2,3,4,5}, arr2{6,7,8,9,10} {} + // constexpr int* begin() { return arr1; } + // constexpr int* end() { return arr1 + 5; } + // constexpr const int* begin() const { return arr2; } + // constexpr const int* end() const { return arr2 + 5; } + // }; + // constexpr int f() { + // Range range{}; + // int sum{0}; + // for(int x : range) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopOverNonConstRangeChoosesNonConstBeginEnd() throws Exception { + assertEvaluationEquals(15); + } + + // class Range { + // int arr1[5]; + // int arr2[5]; + // public: + // constexpr Range():arr1{1,2,3,4,5}, arr2{6,7,8,9,10} {} + // constexpr int* begin() { return arr1; } + // constexpr int* end() { return arr1 + 5; } + // constexpr const int* begin() const { return arr2; } + // constexpr const int* end() const { return arr2 + 5; } + // }; + // constexpr int f() { + // const Range range{}; + // int sum{0}; + // for(int x : range) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopOverConstRangeChoosesConstBeginEnd() throws Exception { + assertEvaluationEquals(40); + } + + // class Range { + // int arr1[5]; + // int arr2[5]; + // public: + // constexpr Range():arr1{1,2,3,4,5}, arr2{6,7,8,9,10} {} + // constexpr int* begin() { return arr1; } + // constexpr int* end() { return arr1 + 5; } + // constexpr const int* begin() const { return arr2; } + // constexpr const int* end() const { return arr2 + 5; } + // }; + // constexpr int f() { + // Range range{}; + // Range const& rangeRef = range; + // int sum{0}; + // for(int x : rangeRef) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopOverConstRefRangeChoosesConstBeginEnd() throws Exception { + assertEvaluationEquals(40); + } + + // class Range { + // int arr[5]; + // public: + // constexpr Range():arr{1,2,3,4,5} {} + // constexpr const int* begin(int i) const { return arr + i; } + // constexpr const int* end() const { return arr + 5; } + // }; + // constexpr int f() { + // Range range{}; + // int sum{0}; + // for(int x : range) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopOverCustomTypeWithInvalidBeginMemberFunction() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // class Range { + // int arr[5]; + // public: + // constexpr Range():arr{1,2,3,4,5} {} + // constexpr const int* begin(int i = 0) const { return arr + i; } + // constexpr const int* end() const { return arr + 5; } + // }; + // constexpr int f() { + // Range range{}; + // int sum{0}; + // for(int x : range) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopOverCustomTypeWithBeginMemberFunctionWithDefaultParameterValue() throws Exception { + assertEvaluationEquals(15); + } + + // namespace ns { + // class Vec { + // public: + // int arr1[5]; + // constexpr Vec():arr1{1,2,3,4,5} {} + // }; + // constexpr int const* begin(Vec const& v) { return v.arr1; } + // constexpr int const* end(Vec const& v) { return v.arr1 + 5; } + // } + // + // + // constexpr int f() { + // ns::Vec v{}; + // int sum{0}; + // for(int x : v) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testDoesArgumentDependentLookupIfBeginEndMemberFunctionsDontExist() throws Exception { + assertEvaluationEquals(15); + } + + // namespace ns { + // class Vec { + // public: + // int arr1[5]; + // int arr2[5]; + // constexpr Vec():arr1{1,2,3,4,5}, arr2{6,7,8,9,10} {} + // constexpr int const* begin() const { return arr2; } + // constexpr int const* end() const { return arr2 + 5; } + // }; + // constexpr int const* begin(Vec const& v) { return v.arr1; } + // constexpr int const* end(Vec const& v) { return v.arr1 + 5; } + // } + // + // + // constexpr int f() { + // ns::Vec v{}; + // int sum{0}; + // for(int x : v) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testChoosesMemberFunctionsOverFreeFunctions() throws Exception { + assertEvaluationEquals(40); + } + + // namespace ns { + // class Vec { + // public: + // int arr1[5]; + // constexpr Vec():arr1{1,2,3,4,5} {} + // constexpr int const* begin() const { return arr1; } + // }; + // constexpr int const* end(Vec const& v) { return v.arr1 + 5; } + // } + // + // + // constexpr int f() { + // ns::Vec v{}; + // int sum{0}; + // for(int x : v) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testDoesntMixMemberFunctionsAndFreeFunctions() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // namespace ns { + // class Vec { + // int arr[5]; + // public: + // constexpr Vec():arr{1,2,3,4,5} {} + // constexpr int const* start() const { return arr; } + // constexpr int size() const { return 5; } + // }; + // template + // constexpr int const* begin(T const& t) { return t.start(); } + // template + // constexpr int const* end(T const& t) { return t.start() + t.size(); } + // } + // + // constexpr int f() { + // ns::Vec v{}; + // int sum{0}; + // for(int x : v) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testWorksWithBeginEndTemplates() throws Exception { + assertEvaluationEquals(15); + } + + // constexpr int f() { + // int sum = 0; + // for(auto x : {1,2,3,4,5}) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(); + public void testRangeBasedForLoopOverInitializerList() throws Exception { + assertEvaluationEquals(15); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ReferenceTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ReferenceTests.java new file mode 100644 index 00000000000..01f49d4245e --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/ReferenceTests.java @@ -0,0 +1,73 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class ReferenceTests extends TestBase { + public static class NonIndexing extends ReferenceTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends ReferenceTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int f() { + // int a { 1 }; + // int &aRef { a }; + // aRef++; + // return a; + // } + + // constexpr int x = f(); + public void testSideEffectsOnReferences() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr int f() { + // int a { 1 }; + // int &aRef { a }; + // aRef = aRef + 1; + // return a; + // } + + // constexpr int x = f(); + public void testAssignmentsOnReferences() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr int f() { + // int a { 1 }; + // int &aRef { a }; + // int &aRefRef { aRef }; + // aRefRef++; + // return a; + // } + + // constexpr auto x = f(); + public void testSideEffectsOnNestedReferences() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr int f() { + // int a { 1 }; + // int &aRef { a }; + // int &aRefRef { aRef }; + // aRefRef = aRef + aRefRef; + // return a; + // } + + // constexpr auto x = f(); + public void testAssignmentOnNestedReferences() throws Exception { + assertEvaluationEquals(2); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/SwitchStatementTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/SwitchStatementTests.java new file mode 100644 index 00000000000..78bddc28834 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/SwitchStatementTests.java @@ -0,0 +1,247 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class SwitchStatementTests extends TestBase { + public static class NonIndexing extends SwitchStatementTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends SwitchStatementTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int f() { + // int x { 1 }; + // switch (x) { + // case 1: + // return 1; + // case 2: + // return 2; + // default: + // return -1; + // } + // } + + // constexpr int x = f(); + public void testSwitchFirstCase() throws Exception { + assertEvaluationEquals(1); + } + + // constexpr int f() { + // int x { 2 }; + // switch (x) { + // case 1: + // return 1; + // case 2: + // return 2; + // default: + // return -1; + // } + // } + + // constexpr int x = f(); + public void testSwitchMiddleCase() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr int f() { + // int x { 3 }; + // switch (x) { + // case 1: + // return 1; + // case 2: + // return 2; + // default: + // return -1; + // } + // } + + // constexpr int x = f(); + public void testSwitchDefault() throws Exception { + assertEvaluationEquals(-1); + } + + // constexpr int f() { + // int x { 1 }; + // switch (x) { + // case 1: + // case 2: + // return 2; + // default: + // return -1; + // } + // } + + // constexpr int x = f(); + public void testSwitchFallThrough() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr int f() { + // int x { 1 }; + // int y = 10; + // switch(x) + // case 1: + // y++; + // y--; + // return y; + // } + + // constexpr int x = f(); + public void testSwitchWithOnlyOneClause1() throws Exception { + assertEvaluationEquals(10); + } + + // constexpr int f() { + // int x { 0 }; + // int y = 10; + // switch(x) + // case 1: + // y++; + // y--; + // return y; + // } + + // constexpr int x = f(); + public void testSwitchWithOnlyOneClause2() throws Exception { + assertEvaluationEquals(9); + } + + + // constexpr int f() { + // int x { 2 }; + // int y = 2; + // switch (x) { + // case 1: + // y = 10; + // break; + // case 2: + // y = 20; + // break; + // default: + // y = 30; + // } + // return y; + // } + + // constexpr int x = f(); + public void testSwitchBreak() throws Exception { + assertEvaluationEquals(20); + } + + // constexpr int f() { + // int x { 3 }; + // int y = 2; + // switch (x) { + // case 1: + // y = 10; + // break; + // case 2: + // y = 20; + // break; + // } + // return y; + // } + + // constexpr int x = f(); + public void testSwitchNoMatchingCaseAndNoDefault() throws Exception { + assertEvaluationEquals(2); + } + + // class Point { + // int x, y; + // public: + // constexpr Point(int x, int y):x{x}, y{y*2} {} + // constexpr int getY() const { return y; } + // }; + // constexpr int f() { + // int x { 2 }; + // int y = 5; + // constexpr Point p{4, 1}; + // + // switch (x) { + // case 1: + // y = 10; + // break; + // case p.getY(): + // y = 20; + // break; + // } + // return y; + // } + + // constexpr int x = f(); + public void testSwitchCaseConstants() throws Exception { + assertEvaluationEquals(20); + } + + // constexpr int triple(int x) { + // return x * 3; + // } + // constexpr int f(int y) { + // switch(int x = triple(y)) { + // case 9: + // return 1; + // case 12: + // return 2; + // case 15: + // return 3; + // default: + // return 4; + // } + // } + + // constexpr int x = f(5); + public void testDeclarationInSwitchStatementController() throws Exception { + assertEvaluationEquals(3); + } + + // enum Color { RED, GREEN, BLUE }; + // constexpr int f(Color color) { + // switch(color) { + // case RED: + // return 1; + // case GREEN: + // return 2; + // case BLUE: + // return 3; + // } + // } + + // constexpr int x = f(BLUE); + public void testSwitchOnEnumValue() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr int f() { + // int arr[] = {1,2,1,3,5,6,1,2,0}; + // int sum{}; + // for(int i : arr) { + // switch(i) { + // case 1: + // sum++; + // break; + // default: + // continue; + // sum += 2; + // } + // } + // return sum; + // } + + // constexpr int x = f(); + public void testSwitchWithNestedContinueStatement() throws Exception { + assertEvaluationEquals(3); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/TestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/TestBase.java new file mode 100644 index 00000000000..ca5399bb3f9 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/TestBase.java @@ -0,0 +1,207 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; +import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration; +import org.eclipse.cdt.core.dom.parser.cpp.ANSICPPParserExtensionConfiguration; +import org.eclipse.cdt.core.dom.parser.cpp.GPPScannerExtensionConfiguration; +import org.eclipse.cdt.core.dom.parser.cpp.ICPPParserExtensionConfiguration; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.parser.FileContent; +import org.eclipse.cdt.core.parser.IParserLogService; +import org.eclipse.cdt.core.parser.IScanner; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IncludeFileContentProvider; +import org.eclipse.cdt.core.parser.NullLogService; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.core.parser.tests.ASTComparer; +import org.eclipse.cdt.core.testplugin.CTestPlugin; +import org.eclipse.cdt.core.testplugin.util.TestSourceReader; +import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser; +import org.eclipse.cdt.internal.core.dom.parser.CStringValue; +import org.eclipse.cdt.internal.core.dom.parser.FloatingPointValue; +import org.eclipse.cdt.internal.core.dom.parser.cpp.GNUCPPSourceParser; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluationOwner; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.parser.ParserException; +import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor; +import org.eclipse.cdt.internal.index.tests.IndexBindingResolutionTestBase; + +public class TestBase extends IndexBindingResolutionTestBase { + private static final String TEST_CODE = ""; + private static final IParserLogService NULL_LOG = new NullLogService(); + private static final ScannerInfo SCANNER_INFO = new ScannerInfo(getStdMap()); + + private static Map getStdMap() { + Map map = new HashMap<>(); + map.put("__SIZEOF_SHORT__", "2"); + map.put("__SIZEOF_INT__", "4"); + map.put("__SIZEOF_LONG__", "8"); + map.put("__SIZEOF_POINTER__", "8"); + return map; + } + + protected void assertEvaluationEquals(boolean expectedValue) throws Exception { + IValue value = getValue(); + Number num = value.numberValue(); + assertNotNull(num); + assertEquals(expectedValue == false, num.longValue() == 0); + } + + protected void assertEvaluationEquals(char expectedValue) throws Exception { + IValue value = getValue(); + Number num = value.numberValue(); + assertNotNull(num); + assertEquals(expectedValue, num.longValue()); + } + + protected void assertEvaluationEquals(long expectedValue) throws Exception { + IValue value = getValue(); + Number num = value.numberValue(); + assertNotNull(num); + assertEquals(expectedValue, num.longValue()); + } + + protected void assertEvaluationEquals(IValue expectedValue) throws Exception { + IValue value = getValue(); + assertEquals(expectedValue, value); + } + + protected void assertEvaluationEquals(String expectedValue) throws Exception { + IValue value = getValue(); + assertInstance(value, CStringValue.class); + CStringValue cstrValue = (CStringValue) value; + assertEquals(expectedValue, cstrValue.cStringValue()); + } + + protected void assertEvaluationEquals(double expectedValue) throws Exception { + IValue value = getValue(); + assertInstance(value, FloatingPointValue.class); + FloatingPointValue floatingPointValue = (FloatingPointValue) value; + assertEquals(expectedValue, floatingPointValue.numberValue().doubleValue(), 0.001); + } + + private IValue getValue() throws Exception { + ICPPASTInitializerClause point = getLastDeclarationInitializer(); + ICPPEvaluation evaluation = ((ICPPEvaluationOwner)point).getEvaluation(); + return evaluation.getValue(point); + } + + protected ICPPASTInitializerClause getLastDeclarationInitializer() throws Exception { + IASTTranslationUnit tu = strategy.getAst(0); + IASTSimpleDeclaration declaration = (IASTSimpleDeclaration) tu.getChildren()[tu.getChildren().length - 1]; + IASTEqualsInitializer initializer = (IASTEqualsInitializer) declaration.getDeclarators()[0].getInitializer(); + return (ICPPASTInitializerClause) initializer.getInitializerClause(); + } + + protected class NonIndexingTestStrategy implements ITestStrategy { + private ICProject cproject; + private StringBuilder[] testData; + private IASTTranslationUnit ast; + + @Override + public ICProject getCProject() { + return cproject; + } + + @Override + public StringBuilder[] getTestData() { + return testData; + } + + @Override + public int getAstCount() { + return 1; + } + + @Override + public IASTTranslationUnit getAst(int index) { + return ast; + } + + @Override + public StringBuilder getAstSource(int index) { + return testData[0]; + } + + @Override + public void setUp() throws Exception { + CTestPlugin plugin = CTestPlugin.getDefault(); + StringBuilder[] builders = TestSourceReader.getContentsForTest(plugin.getBundle(), "parser", TestBase.this.getClass(), getName(), 2); + if(builders.length == 2) { + builders[0].append(builders[1].toString()); + } + testData = new StringBuilder[] { builders[0] }; + ast = parse(testData[0].toString()); + } + + @Override + public void tearDown() throws Exception { + } + + @Override + public IIndex getIndex() { + return null; + } + + @Override + public boolean isCompositeIndex() { + return false; + } + } + + protected static IASTTranslationUnit parse(String code) throws ParserException { + IScanner scanner = createScanner(FileContent.create(TEST_CODE, code.toCharArray()), ParserLanguage.CPP, ParserMode.COMPLETE_PARSE, SCANNER_INFO); + AbstractGNUSourceCodeParser parser = null; + ICPPParserExtensionConfiguration config = new ANSICPPParserExtensionConfiguration(); + parser = new GNUCPPSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config, null); + parser.setMaximumTrivialExpressionsInAggregateInitializers(Integer.MAX_VALUE); + + IASTTranslationUnit tu = parser.parse(); + assertTrue(tu.isFrozen()); + + validateCopy(tu); + + if (parser.encounteredError()) { + throw new ParserException("FAILURE"); //$NON-NLS-1$ + } + + assertEquals(CPPVisitor.getProblems(tu).length, 0); + assertEquals(0, tu.getPreprocessorProblems().length); + return tu; + } + + private static IScanner createScanner(FileContent codeReader, ParserLanguage lang, ParserMode mode, + IScannerInfo scannerInfo) { + IScannerExtensionConfiguration configuration = GPPScannerExtensionConfiguration.getInstance(scannerInfo); + IScanner scanner = new CPreprocessor(codeReader, scannerInfo, lang, NULL_LOG, configuration, + IncludeFileContentProvider.getSavedFilesProvider()); + return scanner; + } + + private static T validateCopy(T tu) { + IASTNode copy = tu.copy(); + assertFalse(copy.isFrozen()); + ASTComparer.assertCopy(tu, copy); + return (T) copy; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/TypeAliasTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/TypeAliasTests.java new file mode 100644 index 00000000000..f2d40b1cc8a --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/TypeAliasTests.java @@ -0,0 +1,47 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class TypeAliasTests extends TestBase { + public static class NonIndexing extends TypeAliasTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends TypeAliasTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int f() { + // typedef int myint; + // myint x = 5; + // x *= 5; + // return x; + // } + + // constexpr int x = f(); + public void testTypedefDeclaration() throws Exception { + assertEvaluationEquals(25); + } + + // constexpr int f() { + // using myint = int; + // myint x = 5; + // x *= 5; + // return x; + // } + + // constexpr int x = f(); + public void testAliasDeclaration() throws Exception { + assertEvaluationEquals(25); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/UnaryExpressionTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/UnaryExpressionTests.java new file mode 100644 index 00000000000..8dbbe057c93 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/UnaryExpressionTests.java @@ -0,0 +1,133 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class UnaryExpressionTests extends TestBase { + public static class NonIndexing extends UnaryExpressionTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends UnaryExpressionTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int doubleIncrement(int n) { + // ++n; + // ++n; + // return n; + // } + + // constexpr int x = doubleIncrement(0); + public void testSimpleSequence() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr int function() { + // int n { 0 }; + // int m { n++ }; + // int o { n++ }; + // return n; + // } + + // constexpr int x = function(); + public void testAssignmentWithPostfixIncrSideEffects() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr int function() { + // int n { 0 }; + // int m { n-- }; + // int o { n-- }; + // return n; + // } + + // constexpr int x = function(); + public void testAssignmentWithPostfixDecrSideEffects() throws Exception { + assertEvaluationEquals(-2); + } + + // constexpr int function() { + // int n { 0 }; + // int m { --n }; + // int o { --n }; + // return n; + // } + + // constexpr int x = function(); + public void testAssignmentWithPrefixDecrSideEffects() throws Exception { + assertEvaluationEquals(-2); + } + + // constexpr int function() { + // int n { 0 }; + // int m { ++n }; + // int o { ++n }; + // return n; + // } + + // constexpr int x = function(); + public void testAssignmentWithPrefixIncrSideEffects() throws Exception { + assertEvaluationEquals(2); + } + + // constexpr int function() { + // int n { 0 }; + // return n++; + // } + + // constexpr int x = function(); + public void testPostfixIncrSemantics() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr int function() { + // int n { 0 }; + // return n++; + // } + + // constexpr int x = function(); + public void testPostfixDecrSemantics() throws Exception { + assertEvaluationEquals(0); + } + + // constexpr int function() { + // int n { 0 }; + // return ++n; + // } + + // constexpr int x = function(); + public void testPrefixIncrSemantics() throws Exception { + assertEvaluationEquals(1); + } + + // constexpr int function() { + // int n { 0 }; + // return --n; + // } + + // constexpr int x = function(); + public void testPrefixDecrSemantics() throws Exception { + assertEvaluationEquals(-1); + } + + // constexpr int f() { + // int x = 2; + // ++(++x); + // return x; + // } + + // constexpr int x = f(); + public void testPrefixIncrementReturnsLvalue() throws Exception { + assertEvaluationEquals(4); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/UnaryOperatorOverloadingTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/UnaryOperatorOverloadingTests.java new file mode 100644 index 00000000000..e6c3caa812f --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/UnaryOperatorOverloadingTests.java @@ -0,0 +1,73 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import junit.framework.TestSuite; + +public class UnaryOperatorOverloadingTests extends TestBase { + public static class NonIndexing extends UnaryOperatorOverloadingTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends UnaryOperatorOverloadingTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // class Point { + // int x, y; + // public: + // constexpr Point(int x, int y):x{x}, y{y} {} + // constexpr Point& operator++() { + // ++x; + // ++y; + // return *this; + // } + // constexpr int getY() const { return y; } + // }; + // + // constexpr int f() { + // Point p{4,5}; + // ++p; + // return p.getY(); + // } + + // constexpr int x = f(); + public void testPrefixIncrementAsMemberFunction() throws Exception { + assertEvaluationEquals(6); + } + + // class Point { + // int x, y; + // friend constexpr Point& operator++(Point&); + // public: + // constexpr Point(int x, int y):x{x}, y{y} {} + // constexpr int getY() const { + // return y; + // } + // }; + // + // constexpr Point& operator++(Point& p) { + // ++p.x; + // ++p.y; + // return p; + // } + // + // constexpr int f() { + // Point p{4,5}; + // ++p; + // return p.getY(); + // } + + // constexpr int x = f(); + public void testPrefixIncrementAsNonMemberFunction() throws Exception { + assertEvaluationEquals(6); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/UserDefinedLiteralTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/UserDefinedLiteralTests.java new file mode 100644 index 00000000000..11b2d092e41 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/UserDefinedLiteralTests.java @@ -0,0 +1,193 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; + +import junit.framework.TestSuite; + +public class UserDefinedLiteralTests extends TestBase { + public static class NonIndexing extends UserDefinedLiteralTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends UserDefinedLiteralTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr unsigned long long operator"" _min(unsigned long long minutes) { + // return minutes * 60; + // } + + // constexpr auto x = 25_min; + public void testUserDefinedIntegerLiteral() throws Exception { + assertEvaluationEquals(1500); + } + + // constexpr unsigned long long operator"" _capitals(const char* str, unsigned long size) { + // unsigned long long count = 0; + // for(int i = 0; i < size; ++i) { + // if(str[i] >= 'A' && str[i] <= 'Z') { + // count++; + // } + // } + // return count; + // } + + // constexpr auto x = "HAllO"_capitals; + public void testUserDefinedStringLiteral() throws Exception { + assertEvaluationEquals(3); + } + + // constexpr bool operator "" _v(char c) { + // switch(c) { + // case 'a': + // case 'e': + // case 'i': + // case 'o': + // case 'u': + // return true; + // default: + // return false; + // } + // } + + // constexpr auto x = 'a'_v; + public void testUserDefinedCharacterLiteral() throws Exception { + assertEvaluationEquals(true); + } + + // constexpr long double operator"" _deg(long double deg) { + // return deg * 3.141592 / 180; + // } + + // constexpr auto x = 100.0_deg; + public void testUserDefinedFloatingPointLiteral() throws Exception { + assertEvaluationEquals(1.74533); + } + + // constexpr unsigned long long operator "" _l(const char *str) { + // int l = 0; + // while(str[l] != '\0') { + // l++; + // } + // return l; + // } + + // constexpr auto x = 20000_l; + public void testFallbackToRawLiteralOperator() throws Exception { + assertEvaluationEquals(5); + } + + // template + // constexpr unsigned operator"" _l() { + // return 5; + // } + + // constexpr int x = 123.20_l; + public void testRawLiteralOperatorTemplate() throws Exception { + assertEvaluationEquals(5); + } + + // constexpr unsigned operator "" _l(unsigned long long x) { + // return 10; + // } + // constexpr unsigned operator "" _l(const char *str) { + // return 20; + // } + + // constexpr int x = 120_l; + public void testChoosesCookedLiteralOverRawLiteralOperatorIfAvailable() throws Exception { + assertEvaluationEquals(10); + } + + // constexpr unsigned operator "" _l(unsigned long long x) { + // return 10; + // } + // template + // constexpr unsigned operator"" _l() { + // return 20; + // } + + // constexpr int x = 120_l; + public void testChoosesCookedLiteralOverRawLiteralTemplateIfAvailable() throws Exception { + assertEvaluationEquals(10); + } + + // constexpr unsigned operator "" _l(long double x) { + // return 10; + // } + // constexpr unsigned operator "" _l(const char *str) { + // return 20; + // } + + // constexpr int x = 120_l; + public void testFallsBackToRawLiteralOperatorIfParameterTypeDoesntMatchUnsignedLongLong() throws Exception { + assertEvaluationEquals(20); + } + + // constexpr unsigned operator "" _l(long double x) { + // return 10; + // } + // template + // constexpr unsigned operator"" _l() { + // return 20; + // } + + // constexpr int x = 120_l; + public void testFallsBackToRawLiteralOperatorTemplateIfParameterTypeDoesntMatchUnsignedLongLong() throws Exception { + assertEvaluationEquals(20); + } + + // constexpr unsigned operator "" _l(unsigned long long x) { + // return 10; + // } + // constexpr unsigned operator "" _l(const char *str) { + // return 20; + // } + + // constexpr int x = 120.0_l; + public void testFallsBackToRawLiteralOperatorIfParameterTypeDoesntMatchLongDouble() throws Exception { + assertEvaluationEquals(20); + } + + // constexpr unsigned operator "" _l(unsigned long long x) { + // return 10; + // } + // template + // constexpr unsigned operator"" _l() { + // return 20; + // } + + // constexpr int x = 120.0_l; + public void testFallsBackToRawLiteralOperatorTemplateIfParameterTypeDoesntMatchLongDouble() throws Exception { + assertEvaluationEquals(20); + } + + // constexpr unsigned operator "" _l(const char *str) { + // return 20; + // } + + // constexpr int x = "hello"_l; + public void testIgnoresRawLiteralOperatorForUserDefinedStringLiterals() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // template + // constexpr unsigned operator"" _l() { + // return 20; + // } + + // constexpr int x = "hello"_l; + public void testIgnoresRawLiteralOperatorTemplateForUserDefinedStringLiterals() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/WhileStatementTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/WhileStatementTests.java new file mode 100644 index 00000000000..b752cffc6fd --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/constexprevaluation/WhileStatementTests.java @@ -0,0 +1,107 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation; + +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; + +import junit.framework.TestSuite; + +public class WhileStatementTests extends TestBase { + public static class NonIndexing extends WhileStatementTests { + public NonIndexing() {setStrategy(new NonIndexingTestStrategy());} + public static TestSuite suite() {return suite(NonIndexing.class);} + } + + public static class SingleProject extends WhileStatementTests { + public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true, false));} + public static TestSuite suite() {return suite(SingleProject.class);} + } + + // constexpr int f(int n) { + // int sum { 0 }; + // while (n > 0) { + // sum += n; + // n--; + // } + // return sum; + // } + + // constexpr int x = f(10); + public void testWhileLoopWithConditionalExpression() throws Exception { + assertEvaluationEquals(55); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // while (true) { + // sum += n; + // n--; + // } + // return sum; + // } + + // constexpr int x = f(10); + public void testEvalShouldAbortOnWhileWitInfiniteLoop() throws Exception { + assertEvaluationEquals(IntegralValue.ERROR); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // while (true) { + // sum += n; + // return 42; + // } + // return sum; + // } + + // constexpr int x = f(10); + public void testReturnInWhileStatement() throws Exception { + assertEvaluationEquals(42); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // while (n > 0) + // sum += n--; + // return sum; + // } + + // constexpr int x = f(10); + public void testWhileLoopWithNonCompoundBodyStatement() throws Exception { + assertEvaluationEquals(55); + } + + // constexpr int f(int n) { + // int sum { 0 }; + // while (n > 0) + // return 42; + // return sum; + // } + + // constexpr int x = f(10); + public void testWhileLoopWithReturnInNonCompoundBodyStatement() throws Exception { + assertEvaluationEquals(42); + } + + // constexpr int triple(int x) { + // return x * 3; + // } + // constexpr int f(int y) { + // int sum = 0; + // while(int x = triple(y--)) { + // sum += x; + // } + // return sum; + // } + + // constexpr int x = f(4); + public void testDeclarationInWhileStatementCondition1() throws Exception { + assertEvaluationEquals(30); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java index d4f4d4486ac..eddd23301ce 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java @@ -530,15 +530,21 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase { } } - class SinglePDOMTestStrategy extends BaseTestStrategy { + protected class SinglePDOMTestStrategy extends BaseTestStrategy { private IIndex index; private ICProject cproject; private StringBuilder[] testData; private IASTTranslationUnit ast; private final boolean cpp; + private final boolean shouldRequireHeaderFile; public SinglePDOMTestStrategy(boolean cpp) { + this(cpp, true); + } + + public SinglePDOMTestStrategy(boolean cpp, boolean shouldRequireHeaderFile) { this.cpp = cpp; + this.shouldRequireHeaderFile = shouldRequireHeaderFile; } @Override @@ -578,8 +584,16 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase { Bundle b = CTestPlugin.getDefault().getBundle(); testData = TestSourceReader.getContentsForTest(b, "parser", IndexBindingResolutionTestBase.this.getClass(), getName(), 2); - if (testData.length < 2) + if(testData.length < 1) { fail("Insufficient test data"); + } else if(shouldRequireHeaderFile && testData.length == 1) { + fail("Insufficient test data"); + } else if(testData.length == 1) { + StringBuilder newTestData[] = new StringBuilder[2]; + newTestData[0] = new StringBuilder(); + newTestData[1] = testData[0]; + testData = newTestData; + } testData[1].insert(0, "#include \"header.h\" " + END_OF_ADDED_CODE_MARKER + "\n"); String headerContents = testData[0].toString(); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java index 4ba12d5bf43..7cca9ea3f26 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java @@ -1949,10 +1949,10 @@ public class IndexBugsTests extends BaseTestCase { try { BindingAssertionHelper aHelper = new BindingAssertionHelper(a, testData[1], index); IEnumerator e1 = aHelper.assertNonProblem("e;", 1, IEnumerator.class); - assertEquals(1, e1.getValue().numericalValue().longValue()); + assertEquals(1, e1.getValue().numberValue().longValue()); BindingAssertionHelper bHelper = new BindingAssertionHelper(b, testData[3], index); IEnumerator e2 = bHelper.assertNonProblem("e;", 1, IEnumerator.class); - assertEquals(2, e2.getValue().numericalValue().longValue()); + assertEquals(2, e2.getValue().numberValue().longValue()); } finally { index.releaseReadLock(); } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionTest.java index e8d845ddb3e..178fb4b0ef7 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCBindingResolutionTest.java @@ -385,7 +385,7 @@ public class IndexCBindingResolutionTest extends IndexBindingResolutionTestBase v= (IVariable) getBindingFromASTName("b;", 1); checkValue(v.getInitialValue(), 0); v= (IVariable) getBindingFromASTName("c;", 1); - assertNull(v.getInitialValue().numericalValue()); + assertNull(v.getInitialValue().numberValue()); IEnumerator e= (IEnumerator) getBindingFromASTName("e0", 2); checkValue(e.getValue(), 0); @@ -401,7 +401,7 @@ public class IndexCBindingResolutionTest extends IndexBindingResolutionTestBase private void checkValue(IValue initialValue, int i) { assertNotNull(initialValue); - final Long numericalValue = initialValue.numericalValue(); + final Number numericalValue = initialValue.numberValue(); assertNotNull(numericalValue); assertEquals(i, numericalValue.intValue()); } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java index 21221577f6c..35e196867f5 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java @@ -175,7 +175,7 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti private void asserValueEquals(IValue initialValue, long i) { assertNotNull(initialValue); - final Long numericalValue = initialValue.numericalValue(); + final Number numericalValue = initialValue.numberValue(); assertNotNull(numericalValue); assertEquals(i, numericalValue.longValue()); } @@ -1476,7 +1476,7 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti v= (IVariable) getBindingFromASTName("b;", 1); asserValueEquals(v.getInitialValue(), 0); v= (IVariable) getBindingFromASTName("c;", 1); - assertNull(v.getInitialValue().numericalValue()); + assertNull(v.getInitialValue().numberValue()); IEnumerator e= (IEnumerator) getBindingFromASTName("e0", 2); asserValueEquals(e.getValue(), 0); @@ -1893,7 +1893,7 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti // constexpr int waldo = foo(); public void testNameLookupInDefaultArgument_432701() { IVariable waldo = getBindingFromASTName("waldo", 5); - assertEquals(42, waldo.getInitialValue().numericalValue().longValue()); + assertEquals(42, waldo.getInitialValue().numberValue().longValue()); } // struct function { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java index 62824df8837..db5016d71d1 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java @@ -62,6 +62,7 @@ import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper.MethodKind; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; @@ -1486,7 +1487,7 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa ICPPTemplateParameterMap paramMap = c256.getTemplateParameterMap(); assertEquals(1, paramMap.getAllParameterPositions().length); ICPPTemplateArgument arg = paramMap.getArgument(0); - assertEquals(Long.valueOf(256), arg.getNonTypeValue().numericalValue()); + assertEquals(Long.valueOf(256), arg.getNonTypeValue().numberValue()); assertInstance(arg.getTypeOfNonTypeValue(), ICPPBasicType.class); ICPPFunction foo = getBindingFromASTName("foo(t)", 3, ICPPFunction.class); @@ -2213,7 +2214,7 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa public void testDependentEnumValue_389009() throws Exception { IEnumerator binding = getBindingFromASTName("id;", 2, IEnumerator.class); IValue value = binding.getValue(); - Long num = value.numericalValue(); + Number num = value.numberValue(); assertNotNull(num); assertEquals(1, num.longValue()); } @@ -2956,4 +2957,42 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa public void testStackOverflow_462764() throws Exception { checkBindings(); } + + // template + // struct base { + // constexpr base() {} + // }; + // + // template + // struct derived : base { + // constexpr derived() : base() {} + // }; + + // derived waldo; + public void testSerializationOfUnknownConstructor_490475() throws Exception { + IASTName waldoName = findName("waldo", 5); + IVariable waldo = getBindingFromASTName("waldo", 5); + IType derivedInt = waldo.getType(); + assertInstance(derivedInt, ICPPClassSpecialization.class); + ICPPClassType derived = ((ICPPClassSpecialization) derivedInt).getSpecializedBinding(); + ICPPMethod constructor = ClassTypeHelper.getMethodInClass(derived, MethodKind.DEFAULT_CTOR, null); + assertInstance(constructor, ICPPConstructor.class); + // Trigger deserialization of constructor chain execution + ((ICPPConstructor) constructor).getConstructorChainExecution(waldoName); + } + + // template + // struct S { + // F f; + // }; + // + // template + // auto foo(F f) -> decltype(S{f}); + + // void bar() { + // foo([]{}); + // } + public void testBracedInitList_490475() throws Exception { + checkBindings(); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java index 68298c998dd..a1a8ff6bb9e 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java @@ -213,7 +213,7 @@ public class IndexUpdateTests extends IndexTestBase { if (value == null) assertNull(v); else - assertEquals(value, v.numericalValue()); + assertEquals(value, v.numberValue()); } finally { fIndex.releaseReadLock(); } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java index fecdf2db081..a33be5d155d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java @@ -386,7 +386,7 @@ public class CPPClassTemplateTests extends PDOMInlineCodeTestBase { ICPPTemplateArgument aT2DefaultArgument = templateParameterAT2.getDefaultValue(); assertNotNull(aT2DefaultArgument); assertTrue(new CPPBasicType(IBasicType.Kind.eInt, 0).isSameType(aT2DefaultArgument.getTypeOfNonTypeValue())); - assertEquals(5, aT2DefaultArgument.getNonTypeValue().numericalValue().longValue()); + assertEquals(5, aT2DefaultArgument.getNonTypeValue().numberValue().longValue()); assertEquals(0, templateParameterAT2.getTemplateNestingLevel()); assertDeclarationCount(pdom, "S", 1); diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java index 4a6096a91ac..3b742d77dd7 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java @@ -12,10 +12,6 @@ *******************************************************************************/ package org.eclipse.cdt.core.suite; -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - import org.eclipse.cdt.core.cdescriptor.tests.CDescriptorOldTests; import org.eclipse.cdt.core.cdescriptor.tests.CDescriptorTests; import org.eclipse.cdt.core.envvar.IEnvironmentVariableManagerTests; @@ -29,6 +25,7 @@ import org.eclipse.cdt.core.model.tests.AllCoreTests; import org.eclipse.cdt.core.model.tests.ElementDeltaTests; import org.eclipse.cdt.core.model.tests.WorkingCopyTests; import org.eclipse.cdt.core.parser.tests.ParserTestSuite; +import org.eclipse.cdt.core.parser.tests.ast2.constexprevaluation.AllConstexprEvalTests; import org.eclipse.cdt.core.parser.tests.rewrite.RewriteTests; import org.eclipse.cdt.core.resources.tests.RefreshScopeTests; import org.eclipse.cdt.internal.index.tests.IndexTests; @@ -41,6 +38,10 @@ import org.eclipse.cdt.utils.StorableCdtVariablesTest; import org.eclipse.cdt.utils.UNCPathConverterTest; import org.eclipse.cdt.utils.WeakHashSetTest; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + /** * @author vhirsl */ @@ -68,10 +69,11 @@ public class AutomatedIntegrationSuite extends TestSuite { if (System.getProperty("cdt.skip.known.test.failures") == null) { suite.addTest(CDescriptorTests.suite()); } + suite.addTest(AllConstexprEvalTests.suite()); + suite.addTest(ParserTestSuite.suite()); suite.addTest(CDescriptorOldTests.suite()); suite.addTest(IEnvironmentVariableManagerTests.suite()); suite.addTest(ErrorParserTests.suite()); - suite.addTest(ParserTestSuite.suite()); suite.addTest(AllCoreTests.suite()); suite.addTest(ElementDeltaTests.suite()); suite.addTest(WorkingCopyTests.suite()); diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java index e5071f2b9a0..461661c3b7a 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java @@ -360,7 +360,7 @@ public class BaseTestCase extends TestCase { protected static void assertVariableValue(IVariable var, long expectedValue) { assertNotNull(var.getInitialValue()); - assertNotNull(var.getInitialValue().numericalValue()); - assertEquals(expectedValue, var.getInitialValue().numericalValue().longValue()); + assertNotNull(var.getInitialValue().numberValue()); + assertEquals(expectedValue, var.getInitialValue().numberValue().longValue()); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java index 357aeeb7f27..76c4db01d01 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java @@ -44,7 +44,7 @@ import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.c.CASTTypeId; import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor; import org.eclipse.cdt.internal.core.dom.parser.c.ICInternalBinding; @@ -309,14 +309,14 @@ public class ASTTypeUtil { } } IValue val= ((IArrayType) type).getSize(); - if (val != null && val != Value.UNKNOWN) { + if (val != null && val != IntegralValue.UNKNOWN) { if (normalize) { if (needSpace) { result.append(SPACE); needSpace = false; } result.append(val.getSignature()); } else { - Long v= val.numericalValue(); + Number v= val.numberValue(); if (v != null) { if (needSpace) { result.append(SPACE); needSpace = false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IValue.java index 31107ecce6e..235a0d5ba14 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IValue.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IValue.java @@ -11,7 +11,9 @@ *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.core.runtime.CoreException; /** * Models a value of a variable, enumerator or expression. @@ -22,13 +24,44 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; */ public interface IValue { /** - * Returns the value as a number, or {@code null} if it is not possible. + * Returns the value as a Long number, or {@code null} if it is not possible. + * @deprecated Use numberValue() instead. */ + @Deprecated Long numericalValue(); /** - * Returns the evaluation object if this value is dependent, or {@code null} otherwise. - * If {@link #numericalValue()} returns {@code null}, {@link #getEvaluation()} returns + * Returns the value as a number, or {@code null} if it is not possible. + * @since 6.0 + */ + Number numberValue(); + + /** + * If this value consists of sub-values, returns the number of these sub-values. Otherwise returns 1. + * @since 6.0 + */ + int numberOfSubValues(); + + /** + * If this value consists of sub-values, returns the sub-value at the given index. + * Otherwise, returns this value (represented as an ICPPEvaluation) if the index 0 is passed. + * EvalFixed.INCOMPLETE is returned if the given index is out of bounds. + * @noreference This method is not intended to be referenced by clients. + */ + ICPPEvaluation getSubValue(int index); + + /** + * If this value consists of sub-values, returns an array containing all of them. + * Otherwise, returns an array containing 1 element representing this value. + * Not all implementations implement this; some may return {@code null}. + * @noreference This method is not intended to be referenced by clients. + */ + ICPPEvaluation[] getAllSubValues(); + + /** + * Returns the evaluation object if this value cannot be represented as a single numerical value, or + * {@code null} otherwise. This cam happen if the value is dependent, or it's a composite value. + * If {@link #numberValue()} returns {@code null}, {@link #getEvaluation()} returns * not {@code null} and vice versa. * @noreference This method is not intended to be referenced by clients. */ @@ -53,4 +86,24 @@ public interface IValue { */ @Deprecated IBinding[] getUnknownBindings(); + + /** + * If this value consists of sub-values, set the sub-value at the given position to the given new value. + * Otherwise, set this value to the given new value. + * Not all implementations implement this; for some, a call to this may have no effect. + * @noreference This method is not intended to be referenced by clients. + */ + void setSubValue(int position, ICPPEvaluation newValue); + + /** + * Make a deep copy of this value. + * @since 6.0 + */ + IValue clone(); + + /** + * Serialize this value to the given type marhsal buffer. + * @noreference This method is not intended to be referenced by clients. + */ + void marshal(ITypeMarshalBuffer buffer) throws CoreException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTInitializerClause.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTInitializerClause.java index 669a66ec9c7..c953cb06d15 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTInitializerClause.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTInitializerClause.java @@ -11,7 +11,6 @@ package org.eclipse.cdt.core.dom.ast.cpp; import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; -import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; /** * C++ specific initializer clause. @@ -20,9 +19,4 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; * @since 5.5 */ public interface ICPPASTInitializerClause extends IASTInitializerClause { - /** - * Returns the evaluation object for this expression. - * @noreference This method is not intended to be referenced by clients. - */ - ICPPEvaluation getEvaluation(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPConstructor.java index 6c8d5e7b18c..89f75606322 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPConstructor.java @@ -10,10 +10,22 @@ *******************************************************************************/ package org.eclipse.cdt.core.dom.ast.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; + /** * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. */ public interface ICPPConstructor extends ICPPMethod { public static final ICPPConstructor[] EMPTY_CONSTRUCTOR_ARRAY = {}; + + /** + * For a constexpr constructor returns the ICPPExecution for its constructor chain. Otherwise returns + * {@code null}. + * @param point The point of instantiation for name lookups. + * @since 6.0 + * @noreference This method is not intended to be referenced by clients. + */ + public ICPPExecution getConstructorChainExecution(IASTNode point); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPField.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPField.java index 2c3d427d6b9..4630dbc198c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPField.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPField.java @@ -18,4 +18,10 @@ import org.eclipse.cdt.core.dom.ast.IField; */ public interface ICPPField extends IField, ICPPMember, ICPPVariable { public static final ICPPField[] EMPTY_CPPFIELD_ARRAY = {}; + + /** + * Returns the position of this field within its class owner's declared fields. + * @since 6.0 + */ + byte getFieldPosition(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java index dc832aaaa34..29d4c5d8bee 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java @@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.parser.ParserException; @@ -173,10 +174,15 @@ public abstract class ASTAmbiguousNode extends ASTNode { return false; } - public final ICPPEvaluation getEvaluation() { + public final ICPPEvaluation getEvaluation() { logAmbiguousNodeError(); return EvalFixed.INCOMPLETE; } + + public final ICPPExecution getExecution() { + logAmbiguousNodeError(); + return null; + } private void logAmbiguousNodeError() { CCorePlugin.log(new ParserException("Encountered an ambiguous node \"" + //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTEnumerator.java index dd35dd4ef72..862634556b1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTEnumerator.java @@ -127,7 +127,7 @@ public abstract class ASTEnumerator extends ASTNode implements IASTEnumerator, I } } if (integralValue == null) { - integralValue= Value.UNKNOWN; + integralValue= IntegralValue.UNKNOWN; } } return integralValue; @@ -151,7 +151,7 @@ public abstract class ASTEnumerator extends ASTNode implements IASTEnumerator, I IValue val; IASTExpression expr= etor.getValue(); if (expr != null) { - val= Value.create(expr); + val= ValueFactory.create(expr); previousExplicitValue = val; delta = 1; if (fixedType == null) { @@ -163,9 +163,9 @@ public abstract class ASTEnumerator extends ASTNode implements IASTEnumerator, I } } else { if (previousExplicitValue != null) { - val = Value.incrementedValue(previousExplicitValue, delta); + val = IntegralValue.incrementedValue(previousExplicitValue, delta); } else { - val = Value.create(delta); + val = IntegralValue.create(delta); } delta++; if (fixedType == null && type instanceof IBasicType) { @@ -196,7 +196,7 @@ public abstract class ASTEnumerator extends ASTNode implements IASTEnumerator, I * @return the type of the incremented value */ public static IBasicType getTypeOfIncrementedValue(IBasicType type, IValue val) { - Long numericalValue = val.numericalValue(); + Number numericalValue = val.numberValue(); if (numericalValue != null) { long longValue = numericalValue.longValue(); if ((type.getKind() != Kind.eInt && type.getKind() != Kind.eInt128) || diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CStringValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CStringValue.java new file mode 100644 index 00000000000..5755a1c05dc --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CStringValue.java @@ -0,0 +1,254 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; +import org.eclipse.core.runtime.CoreException; + +public class CStringValue implements IValue { + private static final Map escapeSequences; + static { + Map map = new HashMap(); + map.put('\'', '\''); + map.put('"', '"'); + map.put('?', '?'); + map.put('\\', '\\'); + map.put('a', '\007'); + map.put('b', '\b'); + map.put('f', '\f'); + map.put('n', '\n'); + map.put('r', '\r'); + map.put('t', '\t'); + map.put('v', '\013'); + escapeSequences = Collections.unmodifiableMap(map); + } + + private final char[] fFixedValue; + + private String fParsedValue; + + private CStringValue(char[] fixedValue) { + fFixedValue = fixedValue; + } + + public static IValue create(char[] fixedValue) { + return new CStringValue(fixedValue); + } + + public String cStringValue() { + if (fParsedValue == null) { + fParsedValue = parseString(); + } + return fParsedValue; + } + + private int indexOfStartQuote() { + final int len = fFixedValue.length; + int i = 0; + while(i < len && fFixedValue[i] != '"') { + ++i; + } + if(i >= len) { + return -1; + } else { + return i; + } + } + + private int indexOfEndQuote() { + int i = fFixedValue.length - 1; + while(i >= 0 && fFixedValue[i] != '"') { + --i; + } + if(i < 0) { + return -1; + } else { + return i; + } + } + + private boolean isRawStringLiteral() { + for(int i = 0; i < indexOfStartQuote(); ++i) { + if(fFixedValue[i] == 'R') { + return true; + } + } + return false; + } + + private int getDelimiterLength() { + if(isRawStringLiteral()) { + int i = indexOfStartQuote(); + int len = 0; + while(i < fFixedValue.length && fFixedValue[i] != '(') { + ++i; + ++len; + } + return len; + } + return 0; + } + + private int getStart() { + return indexOfStartQuote() + getDelimiterLength() + 1; + } + + private int getEnd() { + return indexOfEndQuote() - getDelimiterLength() - 1; + } + + private String parseString() { + // TODO: Reuse code between this and CPPASTLiteralExpression.computeStringLiteralSize(). + boolean isRaw = isRawStringLiteral(); + int end = getEnd(); + + StringBuilder builder = new StringBuilder(); + for(int i = getStart(); i <= end; ++i) { + if(!isRaw && fFixedValue[i] == '\\' && i < end) { + ++i; + + //C-Strings are null-terminated. Therefore, a '\0' character + //denotes the end of the string, even if the literal contains + //more characters after that + if(fFixedValue[i] == '0') { + break; + } else { + i = parseEscapeSequence(i, builder); + } + } else { + builder.append(fFixedValue[i]); + } + } + return builder.toString(); + } + + private int parseEscapeSequence(int i, StringBuilder builder) { + char c = fFixedValue[i]; + Character escapeSequence = escapeSequences.get(c); + if(escapeSequence != null) { + builder.append(escapeSequence); + } else if(c == 'u' && i + 4 <= getEnd()) { + StringBuilder hexStr = new StringBuilder(); + ++i; + for(int end = i + 4; i < end; ++i) { + hexStr.append(fFixedValue[i]); + } + int codePoint = Integer.parseInt(hexStr.toString(), 16); + builder.append(Character.toChars(codePoint)); + } + return i; + } + + @Override + public Long numericalValue() { + return null; + } + + @Override + public Number numberValue() { + return null; + } + + @Override + public int numberOfSubValues() { + String str = cStringValue(); + return str.length(); + } + + @Override + public ICPPEvaluation getSubValue(int index) { + String str = cStringValue(); + Character c = null; + if(index >= 0 && index < str.length()) { + c = str.charAt(index); + } else if(index == str.length()) { + c = '\0'; + } + + if(c != null) { + IValue val = IntegralValue.create(c); + return new EvalFixed(CPPBasicType.CHAR, ValueCategory.PRVALUE, val); + } + return null; + } + + @Override + public ICPPEvaluation[] getAllSubValues() { + return null; + } + + @Override + public ICPPEvaluation getEvaluation() { + return null; + } + + @Override + public char[] getSignature() { + return fFixedValue; + } + + @Override + public int hashCode() { + return CharArrayUtils.hash(getSignature()); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof CStringValue)) { + return false; + } + final CStringValue rhs = (CStringValue) obj; + if (fFixedValue != null) + return CharArrayUtils.equals(fFixedValue, rhs.fFixedValue); + return CharArrayUtils.equals(getSignature(), rhs.getSignature()); + } + + @Deprecated + @Override + public char[] getInternalExpression() { + return CharArrayUtils.EMPTY_CHAR_ARRAY; + } + + @Deprecated + @Override + public IBinding[] getUnknownBindings() { + return IBinding.EMPTY_BINDING_ARRAY; + } + + @Override + public void setSubValue(int position, ICPPEvaluation newValue) { + } + + @Override + public IValue clone() { + char[] newFixedValue = Arrays.copyOf(fFixedValue, fFixedValue.length); + return new CStringValue(newFixedValue); + } + + @Override + public void marshal(ITypeMarshalBuffer buf) throws CoreException { + buf.putShort(ITypeMarshalBuffer.C_STRING_VALUE); + buf.putCharArray(fFixedValue); + } + + public static IValue unmarshal(short firstBytes, ITypeMarshalBuffer buf) throws CoreException { + return new CStringValue(buf.getCharArray()); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java new file mode 100644 index 00000000000..531bbdc35e7 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java @@ -0,0 +1,268 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.cdt.core.dom.ast.IArrayType; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.ICompositeType; +import org.eclipse.cdt.core.dom.ast.IField; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ActivationRecord; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalInitList; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil; +import org.eclipse.core.runtime.CoreException; + +public class CompositeValue implements IValue { + private final ICPPEvaluation[] values; + private ICPPEvaluation evaluation; + + public CompositeValue(ICPPEvaluation evaluation, ICPPEvaluation[] values) { + this.evaluation = evaluation; + this.values = values; + } + + @Override + public Long numericalValue() { + return null; + } + + @Override + public Number numberValue() { + return null; + } + + @Override + public ICPPEvaluation getEvaluation() { + return evaluation; + } + + @Override + public char[] getSignature() { + if(evaluation != null) { + return evaluation.getSignature(); + } + return new char[]{}; + } + + @Deprecated + @Override + public char[] getInternalExpression() { + return CharArrayUtils.EMPTY_CHAR_ARRAY; + } + + @Deprecated + @Override + public IBinding[] getUnknownBindings() { + return IBinding.EMPTY_BINDING_ARRAY; + } + + @Override + public int numberOfSubValues() { + return values.length; + } + + @Override + public ICPPEvaluation getSubValue(final int index) { + return rangeIsValid(index) ? values[index] : EvalFixed.INCOMPLETE; + } + + private boolean rangeIsValid(final int index) { + return numberOfSubValues() > index && index >= 0; + } + + public static IValue create(EvalInitList initList) { + ICPPEvaluation[] values = new ICPPEvaluation[initList.getClauses().length]; + for (int i = 0; i < initList.getClauses().length; i++) { + ICPPEvaluation eval = initList.getClauses()[i]; + values[i] = new EvalFixed(eval.getType(null), eval.getValueCategory(null), eval.getValue(null)); + } + return new CompositeValue(initList, values); + } + + /** + * Creates a value representing an instance of the given array type initialized with + * the elements of the given initializer list. + */ + public static IValue create(EvalInitList initList, IArrayType type) { + Number arraySize = type.getSize().numberValue(); + if (arraySize == null) { + // Array size is dependent. TODO: Handle this? + return IntegralValue.UNKNOWN; + } + IType elementType = type.getType(); + ICPPEvaluation[] values = new ICPPEvaluation[arraySize.intValue()]; + for (int i = 0; i < initList.getClauses().length; i++) { + ICPPEvaluation eval = initList.getClauses()[i]; + IValue value = getValue(elementType, eval); + values[i] = new EvalFixed(elementType, eval.getValueCategory(null), value); + } + return new CompositeValue(initList, values); + } + + /** + * Gets the value of an evaluation, interpreted as a value of the given type. + */ + private static IValue getValue(IType type, ICPPEvaluation eval) { + IValue value; + if (type instanceof IArrayType && eval instanceof EvalInitList) { + value = CompositeValue.create((EvalInitList) eval, (IArrayType) type); + } else if (type instanceof ICompositeType && eval instanceof EvalInitList) { + value = CompositeValue.create((EvalInitList) eval, (ICompositeType) type); + } else if (eval instanceof EvalInitList) { + value = IntegralValue.UNKNOWN; + } else { + value = eval.getValue(null); + } + return value; + } + + /** + * Creates a value representing an instance of the given composite type initialized with + * the elements of the given initializer list. + */ + public static IValue create(EvalInitList initList, ICompositeType type) { + IField[] fields = type.getFields(); + ICPPEvaluation[] values = new ICPPEvaluation[fields.length]; + for (int i = 0; i < fields.length; i++) { + IField field = fields[i]; + ICPPEvaluation eval = initList.getClauses()[i]; + IType fieldType = field.getType(); + IValue value = getValue(fieldType, eval); + values[i] = new EvalFixed(fieldType, eval.getValueCategory(null), value); + } + return new CompositeValue(initList, values); + } + + // The set of class types for which composite value creation is in progress on each thread. + // Used to guard against infinite recursion due to a class (invalidly) aggregating itself. + private static final ThreadLocal> fCreateInProgress = + new ThreadLocal>() { + @Override + protected Set initialValue() { + return new HashSet<>(); + } + }; + + /** + * Creates a value representing an instance of a class type, with the values of the fields + * determined by the default member initializers only. Constructors are not considered + * when determining the values of the fields. + */ + public static CompositeValue create(ICPPClassType classType) { + Set recursionProtectionSet = fCreateInProgress.get(); + if (!recursionProtectionSet.add(classType)) { + return new CompositeValue(null, ICPPEvaluation.EMPTY_ARRAY); + } + try { + ActivationRecord record = new ActivationRecord(); + ICPPEvaluation[] values = new ICPPEvaluation[ClassTypeHelper.getFields(classType, null).length]; + + // recursively create all the base class member variables + ICPPBase[] bases = ClassTypeHelper.getBases(classType, null); + for(ICPPBase base : bases) { + IBinding baseClass = base.getBaseClass(); + if(baseClass instanceof ICPPClassType) { + ICPPClassType baseClassType = (ICPPClassType) baseClass; + ICPPField[] baseFields = ClassTypeHelper.getDeclaredFields(baseClassType, null); + IValue compValue = CompositeValue.create(baseClassType); + for(ICPPField baseField : baseFields) { + int fieldPos = CPPASTFieldReference.getFieldPosition(baseField); + record.update(baseField, compValue.getSubValue(fieldPos)); + // TODO(nathanridge): This won't work with multiple inheritance, since 'fieldPos' + // is a field position in the base class' hierarchy, while values[] expects + // as index a field position in classType's hierarchy. + values[fieldPos] = compValue.getSubValue(fieldPos); + } + } + } + + ICPPField[] fields = ClassTypeHelper.getDeclaredFields(classType, null); + for (ICPPField field : fields) { + final ICPPEvaluation value = EvalUtil.getVariableValue(field, record); + int fieldPos = CPPASTFieldReference.getFieldPosition(field); + record.update(field, value); + values[fieldPos] = value; + } + return new CompositeValue(null, values); + } finally { + recursionProtectionSet.remove(classType); + } + } + + @Override + public ICPPEvaluation[] getAllSubValues() { + return values; + } + + @Override + public void setSubValue(int position, ICPPEvaluation newValue) { + values[position] = newValue; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("["); //$NON-NLS-1$ + for(int i = 0; i < values.length; i++) { + if(values[i] != null) { + builder.append(values[i].toString()); + } else { + builder.append(""); //$NON-NLS-1$ + } + if(i != values.length-1) { + builder.append(", "); //$NON-NLS-1$ + } + } + builder.append("]"); //$NON-NLS-1$ + return builder.toString(); + } + + @Override + public IValue clone() { + ICPPEvaluation[] newValues = new ICPPEvaluation[values.length]; + for(int i = 0; i < newValues.length; i++) { + ICPPEvaluation eval = values[i]; + IValue newValue = eval.getValue(null).clone(); + newValues[i] = new EvalFixed(eval.getType(null), eval.getValueCategory(null), newValue); + } + return new CompositeValue(evaluation, newValues); + } + + @Override + public void marshal(ITypeMarshalBuffer buf) throws CoreException { + buf.putShort(ITypeMarshalBuffer.COMPOSITE_VALUE); + buf.marshalEvaluation(evaluation, true); + buf.putInt(values.length); + for(ICPPEvaluation value : values) { + buf.marshalEvaluation(value, true); + } + } + + public static IValue unmarshal(short firstBytes, ITypeMarshalBuffer buf) throws CoreException { + ICPPEvaluation evaluation = (ICPPEvaluation)buf.unmarshalEvaluation(); + int len = buf.getInt(); + ICPPEvaluation values[] = new ICPPEvaluation[len]; + for(int i = 0; i < len; i++) { + values[i] = (ICPPEvaluation)buf.unmarshalEvaluation(); + } + return new CompositeValue(evaluation, values); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FloatingPointValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FloatingPointValue.java new file mode 100644 index 00000000000..2a4780dc7b9 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FloatingPointValue.java @@ -0,0 +1,184 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser; + +import java.util.Arrays; + +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; +import org.eclipse.core.runtime.CoreException; + +public class FloatingPointValue implements IValue { + private final char[] fFixedValue; + + private FloatingPointValue(char[] fixedValue) { + fFixedValue = fixedValue; + } + + public static FloatingPointValue create(char[] fixedValue) { + return new FloatingPointValue(fixedValue); + } + + public static FloatingPointValue create(double value) { + return new FloatingPointValue(toCharArray(value)); + } + + @Override + public Long numericalValue() { + return null; // not a Long + } + + @Override + public Number numberValue() { + return parseDouble(fFixedValue); + } + + private static Double parseDouble(char[] value) { + double result = 0.0; + int i = 0; + int len = value.length; + + while(i < len && value[i] >= '0' && value[i] <= '9') { + int digit = value[i] - '0'; + result = result * 10 + digit; + ++i; + } + + if(i < len && value[i] == '.') { + ++i; + } + + double div = 10.0; + while(i < len && value[i] >= '0' && value[i] <= '9') { + int digit = value[i] - '0'; + result += digit / div; + div *= 10.0; + ++i; + } + + if(i < len && (value[i] == 'e' || value[i] == 'E')) { + ++i; + } + + boolean exponentIsPositive = true; + if(i < len && (value[i] == '+' || value[i] == '-')) { + exponentIsPositive = (value[i] == '+'); + ++i; + } + + int exponent = 0; + while(i < len && value[i] >= '0' && value[i] <= '9') { + int digit = value[i] - '0'; + exponent = exponent * 10 + digit; + ++i; + } + + if(i < len && (value[i] == 'l' || value[i] == 'L' || value[i] == 'f' || value[i] == 'F')) { + ++i; + } + + if(i == len) { + if(!exponentIsPositive) { + exponent *= -1; + } + return result * Math.pow(10, exponent); + } + return null; + } + + @Override + public int numberOfSubValues() { + return 1; + } + + @Override + public ICPPEvaluation getSubValue(int index) { + if(index == 0) { + return getEvaluation(); + } + return EvalFixed.INCOMPLETE; + } + + @Override + public ICPPEvaluation[] getAllSubValues() { + return new ICPPEvaluation[]{ getEvaluation() }; + } + + @Override + public ICPPEvaluation getEvaluation() { + return null; + } + + @Override + public char[] getSignature() { + return fFixedValue; + } + + @Override + public int hashCode() { + return CharArrayUtils.hash(getSignature()); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof FloatingPointValue)) { + return false; + } + final FloatingPointValue rhs = (FloatingPointValue) obj; + if (fFixedValue != null) + return CharArrayUtils.equals(fFixedValue, rhs.fFixedValue); + return CharArrayUtils.equals(getSignature(), rhs.getSignature()); + } + + @Deprecated + @Override + public char[] getInternalExpression() { + return CharArrayUtils.EMPTY_CHAR_ARRAY; + } + + @Deprecated + @Override + public IBinding[] getUnknownBindings() { + return IBinding.EMPTY_BINDING_ARRAY; + } + + @Override + public void setSubValue(int position, ICPPEvaluation newValue) { + } + + private static char[] toCharArray(double value) { + StringBuilder buf= new StringBuilder(); + buf.append(value); + return CharArrayUtils.extractChars(buf); + } + + @Override + public String toString() { + return new String(getSignature()); + } + + @Override + public IValue clone() { + char[] newFixedValue = Arrays.copyOf(fFixedValue, fFixedValue.length); + return new FloatingPointValue(newFixedValue); + } + + @Override + public void marshal(ITypeMarshalBuffer buf) throws CoreException { + buf.putShort(ITypeMarshalBuffer.FLOATING_POINT_VALUE); + buf.putCharArray(fFixedValue); + } + + public static IValue unmarshal(short firstBytes, ITypeMarshalBuffer buf) throws CoreException { + return new FloatingPointValue(buf.getCharArray()); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ISerializableEvaluation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ISerializableEvaluation.java index 5c540554457..96565101a58 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ISerializableEvaluation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ISerializableEvaluation.java @@ -13,8 +13,14 @@ package org.eclipse.cdt.internal.core.dom.parser; import org.eclipse.core.runtime.CoreException; /** - * Interface for marshalling types for storage in the index. + * Interface for marshalling ICPPEvaluation objects for storage in the index. */ public interface ISerializableEvaluation { + /** + * Marshals an ICPPEvaluation object for storage in the index. + * + * @param buffer The buffer that will hold the marshalled ICPPEvaluation object. + * @param includeValue Specifies whether nested IValue objects should be marshalled as well. + * */ void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ISerializableExecution.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ISerializableExecution.java new file mode 100644 index 00000000000..80db9e83926 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ISerializableExecution.java @@ -0,0 +1,24 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser; + +import org.eclipse.core.runtime.CoreException; + +/** + * Interface for marshalling ICPPExecution objects for storage in the index. + */ +public interface ISerializableExecution { + /** + * Marshals an ICPPExecution object for storage in the index. + * + * @param buffer The buffer that will hold the marshalled ICPPExecution object. + * @param includeValue Specifies whether nested IValue objects should be marshalled as well. + * */ + void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException; +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java index 830aa6a6306..a8d982bd13b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java @@ -23,42 +23,76 @@ import org.eclipse.core.runtime.CoreException; * Buffer for marshalling and unmarshalling types. */ public interface ITypeMarshalBuffer { - final static byte BASIC_TYPE = 0x01; - final static byte POINTER_TYPE = 0x02; - final static byte ARRAY_TYPE = 0x03; - final static byte CVQUALIFIER_TYPE = 0x04; - final static byte FUNCTION_TYPE = 0x05; - final static byte REFERENCE_TYPE = 0x06; - final static byte POINTER_TO_MEMBER_TYPE = 0x07; - final static byte PACK_EXPANSION_TYPE = 0x08; - final static byte PROBLEM_TYPE = 0x09; - final static byte VALUE = 0x0A; - final static byte DEPENDENT_EXPRESSION_TYPE = 0x0B; - final static byte UNKNOWN_MEMBER = 0x0C; - final static byte UNKNOWN_MEMBER_CLASS_INSTANCE = 0x0D; - final static byte DEFERRED_CLASS_INSTANCE = 0x0E; - final static byte TYPE_TRANSFORMATION = 0x0F; - final static byte UNKNOWN_MEMBER_TYPE = 0x10; + final static byte + BASIC_TYPE = 0x01, + POINTER_TYPE = 0x02, + ARRAY_TYPE = 0x03, + CVQUALIFIER_TYPE = 0x04, + FUNCTION_TYPE = 0x05, + REFERENCE_TYPE = 0x06, + POINTER_TO_MEMBER_TYPE = 0x07, + PACK_EXPANSION_TYPE = 0x08, + PROBLEM_TYPE = 0x09, + VALUE = 0x0A, + DEPENDENT_EXPRESSION_TYPE = 0x0B, + UNKNOWN_MEMBER = 0x0C, + UNKNOWN_MEMBER_CLASS_INSTANCE = 0x0D, + DEFERRED_CLASS_INSTANCE = 0x0E, + TYPE_TRANSFORMATION = 0x0F, + UNKNOWN_MEMBER_TYPE = 0x10, + INITIALIZER_LIST_TYPE = 0x11, + DEFERRED_FUNCTION = 0x12; // Can add more types up to 0x1C, after that it will collide with TypeMarshalBuffer.UNSTORABLE_TYPE. + + final static byte + INTEGRAL_VALUE = 0x01, + FLOATING_POINT_VALUE = 0x02, + C_STRING_VALUE = 0x03, + COMPOSITE_VALUE = 0x04; + // Can add more values up to 0x1C, after that it will collide with TypeMarshalBuffer.UNSTORABLE_TYPE. final static byte - EVAL_BINARY = 0x01, - EVAL_BINARY_TYPE_ID = 0x02, - EVAL_BINDING = 0x03, - EVAL_COMMA = 0x04, - EVAL_COMPOUND = 0x05, - EVAL_CONDITIONAL = 0x06, - EVAL_FIXED = 0x07, - EVAL_FUNCTION_CALL = 0x08, - EVAL_FUNCTION_SET = 0x09, - EVAL_ID = 0x0A, - EVAL_INIT_LIST = 0x0B, - EVAL_MEMBER_ACCESS = 0x0C, - EVAL_PARAMETER_PACK = 0x0D, - EVAL_TYPE_ID = 0x0E, - EVAL_UNARY = 0x0F, - EVAL_UNARY_TYPE_ID = 0x10; + EVAL_BINARY = 0x01, + EVAL_BINARY_TYPE_ID = 0x02, + EVAL_BINDING = 0x03, + EVAL_COMMA = 0x04, + EVAL_COMPOUND = 0x05, + EVAL_CONDITIONAL = 0x06, + EVAL_FIXED = 0x07, + EVAL_FUNCTION_CALL = 0x08, + EVAL_FUNCTION_SET = 0x09, + EVAL_ID = 0x0A, + EVAL_INIT_LIST = 0x0B, + EVAL_MEMBER_ACCESS = 0x0C, + EVAL_PARAMETER_PACK = 0x0D, + EVAL_TYPE_ID = 0x0E, + EVAL_UNARY = 0x0F, + EVAL_UNARY_TYPE_ID = 0x10, + EVAL_CONSTRUCTOR = 0x11, + EVAL_REFERENCE = 0x12, + EVAL_POINTER = 0x13, + EVAL_COMPOSITE_ACCESS = 0x14; // Can add more evaluations up to 0x1C, after that it will collide with TypeMarshalBuffer.UNSTORABLE_TYPE. + + final static byte + EXEC_COMPOUND_STATEMENT = 0x01, + EXEC_BREAK = 0x02, + EXEC_CASE = 0x03, + EXEC_CONTINUE = 0x04, + EXEC_DECLARATION_STATEMENT = 0x05, + EXEC_DECLARATOR = 0x06, + EXEC_DEFAULT = 0x07, + EXEC_SIMPLE_DECLARATION = 0x08, + EXEC_RETURN = 0x09, + EXEC_EXPRESSION_STATEMENT = 0x0A, + EXEC_IF = 0x0B, + EXEC_WHILE = 0x0C, + EXEC_DO = 0x0D, + EXEC_FOR = 0x0E, + EXEC_RANGE_BASED_FOR = 0x0F, + EXEC_SWITCH = 0x10, + EXEC_CONSTRUCTOR_CHAIN = 0x11; + // Can add more executions up to 0x1C, after that it will collide with TypeMarshalBuffer.UNSTORABLE_TYPE. static final short KIND_MASK = 0x001F; @@ -82,6 +116,7 @@ public interface ITypeMarshalBuffer { IValue unmarshalValue() throws CoreException; IBinding unmarshalBinding() throws CoreException; ISerializableEvaluation unmarshalEvaluation() throws CoreException; + ISerializableExecution unmarshalExecution() throws CoreException; ICPPTemplateArgument unmarshalTemplateArgument() throws CoreException; int getByte() throws CoreException; int getFixedInt() throws CoreException; @@ -107,6 +142,7 @@ public interface ITypeMarshalBuffer { void marshalValue(IValue value) throws CoreException; void marshalBinding(IBinding binding) throws CoreException; void marshalEvaluation(ISerializableEvaluation eval, boolean includeValue) throws CoreException; + void marshalExecution(ISerializableExecution exec, boolean includeValue) throws CoreException; void marshalTemplateArgument(ICPPTemplateArgument arg) throws CoreException; void putByte(byte data); void putFixedInt(int data); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IntegralValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IntegralValue.java new file mode 100644 index 00000000000..b35bf5a1298 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IntegralValue.java @@ -0,0 +1,349 @@ +/******************************************************************************* + * Copyright (c) 2008, 2014 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser; + +import java.util.Arrays; + +import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinary; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinding; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; +import org.eclipse.cdt.internal.core.pdom.dom.TypeMarshalBuffer; +import org.eclipse.core.runtime.CoreException; + +/** + * Represents values of variables, enumerators or expressions. The primary purpose of + * the representation is to support instantiation of templates with non-type template parameters. + */ +public class IntegralValue implements IValue { + public static final int MAX_RECURSION_DEPTH = 25; + + // IntegralValue.THIS represents the this pointer inside a member function / constructor. + public static final IntegralValue THIS = new IntegralValue("this".toCharArray(), null); //$NON-NLS-1$ + + // IntegralValue.UNKNOWN indicates general inability to determine a value. It doesn't have to be an error, + // it could be that evaluation ran into a performance limit, or that we can't model this kind of + // value (such as a pointer to a function). + public static final IntegralValue UNKNOWN = new IntegralValue("".toCharArray(), null) { //$NON-NLS-1$ + @Override + public void setSubValue(int position, ICPPEvaluation newValue) { + throw new UnsupportedOperationException(); + } + }; + + // IntegralValue.ERROR indicates that an error, such as a substitution failure, occurred during evaluation. + public static final IntegralValue ERROR= new IntegralValue("".toCharArray(), null); //$NON-NLS-1$ + + public static final IntegralValue NOT_INITIALIZED= new IntegralValue("<__>".toCharArray(), null); //$NON-NLS-1$ + + private static final char UNIQUE_CHAR = '_'; + + private final static IntegralValue[] TYPICAL= { + new IntegralValue(new char[] {'0'}, null), + new IntegralValue(new char[] {'1'}, null), + new IntegralValue(new char[] {'2'}, null), + new IntegralValue(new char[] {'3'}, null), + new IntegralValue(new char[] {'4'}, null), + new IntegralValue(new char[] {'5'}, null), + new IntegralValue(new char[] {'6'}, null)}; + + private static int sUnique= 0; + + // The following invariant always holds: (fFixedValue == null) != (fEvaluation == null) + private final char[] fFixedValue; + private ICPPEvaluation fEvaluation; + private char[] fSignature; + + private IntegralValue(char[] fixedValue, ICPPEvaluation evaluation) { + assert (fixedValue == null) != (evaluation == null); + fFixedValue = fixedValue; + fEvaluation = evaluation; + } + + @Override + public Long numericalValue() { + return (Long) numberValue(); // IntegralValue.numberValue() always returns a Long + } + + @Override + public Number numberValue() { + return fFixedValue == null ? null : parseLong(fFixedValue); + } + + @Override + public ICPPEvaluation getEvaluation() { + return fEvaluation; + } + + @Override + public char[] getSignature() { + if (fSignature == null) { + fSignature = fFixedValue != null ? fFixedValue : fEvaluation.getSignature(); + } + return fSignature; + } + + @Deprecated + @Override + public char[] getInternalExpression() { + return CharArrayUtils.EMPTY_CHAR_ARRAY; + } + + @Deprecated + @Override + public IBinding[] getUnknownBindings() { + return IBinding.EMPTY_BINDING_ARRAY; + } + + @Override + public void marshal(ITypeMarshalBuffer buf) throws CoreException { + if (UNKNOWN == this) { + buf.putShort((short) (ITypeMarshalBuffer.INTEGRAL_VALUE | ITypeMarshalBuffer.FLAG1)); + } else if(THIS == this) { + buf.putShort((short) (ITypeMarshalBuffer.INTEGRAL_VALUE | ITypeMarshalBuffer.FLAG5)); + } else { + Number num= numberValue(); + if (num != null) { + long lv= num.longValue(); + if (lv >= 0) { + buf.putShort((short) (ITypeMarshalBuffer.INTEGRAL_VALUE | ITypeMarshalBuffer.FLAG2)); + buf.putLong(lv); + } else { + buf.putShort((short) (ITypeMarshalBuffer.INTEGRAL_VALUE | ITypeMarshalBuffer.FLAG3)); + buf.putLong(-lv); + } + } else if (fFixedValue != null) { + buf.putShort((short) (ITypeMarshalBuffer.INTEGRAL_VALUE | ITypeMarshalBuffer.FLAG4)); + buf.putCharArray(fFixedValue); + } else { + buf.putShort(ITypeMarshalBuffer.INTEGRAL_VALUE); + fEvaluation.marshal(buf, true); + } + } + } + + public static IValue unmarshal(short firstBytes, ITypeMarshalBuffer buf) throws CoreException { + if (firstBytes == TypeMarshalBuffer.NULL_TYPE) + return IntegralValue.UNKNOWN; + if ((firstBytes & ITypeMarshalBuffer.FLAG1) != 0) + return IntegralValue.UNKNOWN; + if ((firstBytes & ITypeMarshalBuffer.FLAG2) != 0) + return IntegralValue.create(buf.getLong()); + if ((firstBytes & ITypeMarshalBuffer.FLAG3) != 0) + return IntegralValue.create(-buf.getLong()); + if ((firstBytes & ITypeMarshalBuffer.FLAG4) != 0) + return new IntegralValue(buf.getCharArray(), null); + if ((firstBytes & ITypeMarshalBuffer.FLAG5) != 0) + return IntegralValue.THIS; + + ISerializableEvaluation eval= buf.unmarshalEvaluation(); + if (eval instanceof ICPPEvaluation) + return new IntegralValue(null, (ICPPEvaluation) eval); + return IntegralValue.UNKNOWN; + } + + @Override + public int hashCode() { + return CharArrayUtils.hash(getSignature()); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IntegralValue)) { + return false; + } + final IntegralValue rhs = (IntegralValue) obj; + return CharArrayUtils.equals(getSignature(), rhs.getSignature()); + } + + /** + * For debugging only. + */ + @Override + public String toString() { + return new String(getSignature()); + } + + /** + * Creates a value representing the given number. + */ + public static IntegralValue create(long value) { + if (value >= 0 && value < TYPICAL.length) + return TYPICAL[(int) value]; + return new IntegralValue(toCharArray(value), null); + } + + /** + * Creates a value object representing the given boolean value. + */ + public static IntegralValue create(boolean value) { + return create(value ? 1 : 0); + } + + /** + * Creates a value representing the given template parameter + * in the given template. + */ + public static IntegralValue create(ICPPTemplateDefinition template, ICPPTemplateNonTypeParameter tntp) { + EvalBinding eval = new EvalBinding(tntp, null, template); + return new IntegralValue(null, eval); + } + + /** + * Create a value wrapping the given evaluation. + */ + public static IntegralValue create(ICPPEvaluation eval) { + return new IntegralValue(null, eval); + } + + public static IValue incrementedValue(IValue value, int increment) { + if (value == UNKNOWN) + return UNKNOWN; + Number val = value.numberValue(); + if (val != null) { + return create(val.longValue() + increment); + } + ICPPEvaluation arg1 = value.getEvaluation(); + EvalFixed arg2 = new EvalFixed(CPPBasicType.INT, ValueCategory.PRVALUE, create(increment)); + return create(new EvalBinary(IASTBinaryExpression.op_plus, arg1, arg2, arg1.getTemplateDefinition())); + } + + /** + * Tests whether the value is a template parameter (or a parameter pack). + * + * @return the parameter id of the parameter, or -1 if it is not a template + * parameter. + */ + public static int isTemplateParameter(IValue tval) { + ICPPEvaluation eval = tval.getEvaluation(); + if (eval instanceof EvalBinding) { + return ((EvalBinding) eval).getTemplateParameterID(); + } + return -1; + } + + /** + * Tests whether the value references some template parameter. + */ + public static boolean referencesTemplateParameter(IValue tval) { + ICPPEvaluation eval = tval.getEvaluation(); + if (eval == null) + return false; + return eval.referencesTemplateParameter(); + } + + /** + * Tests whether the value depends on a template parameter. + */ + public static boolean isDependentValue(IValue nonTypeValue) { + if (nonTypeValue == null) + return false; + ICPPEvaluation eval = nonTypeValue.getEvaluation(); + return eval != null && eval.isValueDependent(); + } + + /** + * Creates a value off its canonical representation. + */ + public static IValue fromInternalRepresentation(ICPPEvaluation evaluation) { + return new IntegralValue(null, evaluation); + } + + /** + * Creates a unique value needed during template instantiation. + */ + public static IValue unique() { + StringBuilder buf= new StringBuilder(10); + buf.append(UNIQUE_CHAR); + buf.append(++sUnique); + return new IntegralValue(CharArrayUtils.extractChars(buf), null); + } + + /** + * Parses a long, returns null if not possible + */ + private static Long parseLong(char[] value) { + final long maxvalue= Long.MAX_VALUE / 10; + final int len= value.length; + boolean negative= false; + long result = 0; + int i= 0; + + if (len > 0 && value[0] == '-') { + negative = true; + i++; + } + if (i == len) + return null; + + for (; i < len; i++) { + if (result > maxvalue) + return null; + + final int digit= (value[i] - '0'); + if (digit < 0 || digit > 9) + return null; + result= result * 10 + digit; + } + return negative ? -result : result; + } + + /** + * Converts long to a char array + */ + private static char[] toCharArray(long value) { + StringBuilder buf= new StringBuilder(); + buf.append(value); + return CharArrayUtils.extractChars(buf); + } + + @Override + public int numberOfSubValues() { + return 1; + } + + @Override + public ICPPEvaluation getSubValue(int index) { + return index == 0 ? (fEvaluation != null ? fEvaluation : EvalFixed.INCOMPLETE) : EvalFixed.INCOMPLETE; + } + + @Override + public ICPPEvaluation[] getAllSubValues() { + return new ICPPEvaluation[] { getEvaluation() }; + } + + @Override + public void setSubValue(int position, ICPPEvaluation newValue) { + if (fEvaluation == null) { + throw new RuntimeException("trying to set incomplete value"); //$NON-NLS-1$ + } + if (position == 0) { + fEvaluation = newValue; + } else { + throw new RuntimeException("invalid offset in POD value: " + position); //$NON-NLS-1$ + } + } + + @Override + public IValue clone() { + char[] newFixedValue = fFixedValue != null ? Arrays.copyOf(fFixedValue, fFixedValue.length) : null; + return new IntegralValue(newFixedValue, fEvaluation); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java index 3c477a76c8d..7188e3b6b4f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java @@ -30,8 +30,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit; import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.Linkage; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.parser.ParserMessages; import org.eclipse.core.runtime.PlatformObject; @@ -326,6 +328,10 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I public IValue getInitialValue() { return null; } + + public ICPPEvaluation getInitializerEvaluation() { + return EvalFixed.INCOMPLETE; + } public boolean isAnonymous() { return false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/SizeofCalculator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/SizeofCalculator.java index 0daa3168f2d..afcdf72a2e8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/SizeofCalculator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/SizeofCalculator.java @@ -273,7 +273,7 @@ public class SizeofCalculator { IValue value = type.getSize(); if (value == null) return null; - Long numElements = value.numericalValue(); + Number numElements = value.numberValue(); if (numElements == null) return null; IType elementType = type.getType(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java deleted file mode 100644 index 8c66e80b832..00000000000 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java +++ /dev/null @@ -1,740 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008, 2016 Wind River Systems, Inc. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Markus Schorn - initial API and implementation - * Sergey Prigogin (Google) - *******************************************************************************/ -package org.eclipse.cdt.internal.core.dom.parser; - -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_alignof; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_nothrow_constructor; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_nothrow_copy; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_assign; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_constructor; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_copy; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_destructor; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_virtual_destructor; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_abstract; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_class; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_empty; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_enum; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_final; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_literal_type; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_pod; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_polymorphic; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_standard_layout; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivial; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivially_copyable; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_union; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeof; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeid; -import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; - -import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; -import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; -import org.eclipse.cdt.core.dom.ast.IASTBinaryTypeIdExpression; -import org.eclipse.cdt.core.dom.ast.IASTCastExpression; -import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; -import org.eclipse.cdt.core.dom.ast.IASTExpression; -import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; -import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; -import org.eclipse.cdt.core.dom.ast.IASTIdExpression; -import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; -import org.eclipse.cdt.core.dom.ast.IASTNode; -import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; -import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; -import org.eclipse.cdt.core.dom.ast.IBinding; -import org.eclipse.cdt.core.dom.ast.ICompositeType; -import org.eclipse.cdt.core.dom.ast.IEnumeration; -import org.eclipse.cdt.core.dom.ast.IEnumerator; -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.ICPPASTInitializerClause; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; -import org.eclipse.cdt.core.parser.util.CharArrayUtils; -import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; -import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; -import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; -import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; -import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinary; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinding; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeTraits; -import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator; -import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException; -import org.eclipse.cdt.internal.core.pdom.dom.TypeMarshalBuffer; -import org.eclipse.core.runtime.CoreException; - -/** - * Represents values of variables, enumerators or expressions. The primary purpose of - * the representation is to support instantiation of templates with non-type template parameters. - */ -public class Value implements IValue { - public static final int MAX_RECURSION_DEPTH = 25; - // Value.UNKNOWN indicates general inability to determine a value. It doesn't have to be an error, - // it could be that evaluation ran into a performance limit, or that we can't model this kind of - // value (such as a pointer to a function). - public static final Value UNKNOWN= new Value("".toCharArray(), null); //$NON-NLS-1$ - // Value.ERROR indicates that an error, such as a substitution failure, occurred during evaluation. - public static final Value ERROR= new Value("".toCharArray(), null); //$NON-NLS-1$ - public static final Value NOT_INITIALIZED= new Value("<__>".toCharArray(), null); //$NON-NLS-1$ - - private static final Number VALUE_CANNOT_BE_DETERMINED = new Number() { - @Override - public int intValue() { throw new UnsupportedOperationException(); } - - @Override - public long longValue() { throw new UnsupportedOperationException(); } - - @Override - public float floatValue() { throw new UnsupportedOperationException(); } - - @Override - public double doubleValue() { throw new UnsupportedOperationException(); } - }; - - private static final char UNIQUE_CHAR = '_'; - - private final static IValue[] TYPICAL= { - new Value(new char[] {'0'}, null), - new Value(new char[] {'1'}, null), - new Value(new char[] {'2'}, null), - new Value(new char[] {'3'}, null), - new Value(new char[] {'4'}, null), - new Value(new char[] {'5'}, null), - new Value(new char[] {'6'}, null)}; - - - private static int sUnique= 0; - - // The following invariant always holds: (fFixedValue == null) != (fEvaluation == null) - private final char[] fFixedValue; - private final ICPPEvaluation fEvaluation; - private char[] fSignature; - - private Value(char[] fixedValue, ICPPEvaluation evaluation) { - assert (fixedValue == null) != (evaluation == null); - fFixedValue = fixedValue; - fEvaluation = evaluation; - } - - @Override - public Long numericalValue() { - return fFixedValue == null ? null : parseLong(fFixedValue); - } - - @Override - public ICPPEvaluation getEvaluation() { - return fEvaluation; - } - - @Override - public char[] getSignature() { - if (fSignature == null) { - fSignature = fFixedValue != null ? fFixedValue : fEvaluation.getSignature(); - } - return fSignature; - } - - @Deprecated - @Override - public char[] getInternalExpression() { - return CharArrayUtils.EMPTY_CHAR_ARRAY; - } - - @Deprecated - @Override - public IBinding[] getUnknownBindings() { - return IBinding.EMPTY_BINDING_ARRAY; - } - - public void marshal(ITypeMarshalBuffer buf) throws CoreException { - if (UNKNOWN == this) { - buf.putShort((short) (ITypeMarshalBuffer.VALUE | ITypeMarshalBuffer.FLAG1)); - } else { - Long num= numericalValue(); - if (num != null) { - long lv= num; - if (lv >= 0) { - buf.putShort((short) (ITypeMarshalBuffer.VALUE | ITypeMarshalBuffer.FLAG2)); - buf.putLong(lv); - } else { - buf.putShort((short) (ITypeMarshalBuffer.VALUE | ITypeMarshalBuffer.FLAG3)); - buf.putLong(-lv); - } - } else if (fFixedValue != null) { - buf.putShort((short) (ITypeMarshalBuffer.VALUE | ITypeMarshalBuffer.FLAG4)); - buf.putCharArray(fFixedValue); - } else { - buf.putShort(ITypeMarshalBuffer.VALUE); - fEvaluation.marshal(buf, true); - } - } - } - - public static IValue unmarshal(ITypeMarshalBuffer buf) throws CoreException { - short firstBytes= buf.getShort(); - if (firstBytes == TypeMarshalBuffer.NULL_TYPE) - return Value.UNKNOWN; - if ((firstBytes & ITypeMarshalBuffer.FLAG1) != 0) - return Value.UNKNOWN; - if ((firstBytes & ITypeMarshalBuffer.FLAG2) != 0) - return Value.create(buf.getLong()); - if ((firstBytes & ITypeMarshalBuffer.FLAG3) != 0) - return Value.create(-buf.getLong()); - if ((firstBytes & ITypeMarshalBuffer.FLAG4) != 0) - return new Value(buf.getCharArray(), null); - - ISerializableEvaluation eval= buf.unmarshalEvaluation(); - if (eval instanceof ICPPEvaluation) - return new Value(null, (ICPPEvaluation) eval); - return Value.UNKNOWN; - } - - @Override - public int hashCode() { - return CharArrayUtils.hash(getSignature()); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Value)) { - return false; - } - final Value rhs = (Value) obj; - if (fFixedValue != null) - return CharArrayUtils.equals(fFixedValue, rhs.fFixedValue); - return CharArrayUtils.equals(getSignature(), rhs.getSignature()); - } - - /** - * For debugging only. - */ - @Override - public String toString() { - return new String(getSignature()); - } - - /** - * Creates a value representing the given number. - */ - public static IValue create(long value) { - if (value >= 0 && value < TYPICAL.length) - return TYPICAL[(int) value]; - return new Value(toCharArray(value), null); - } - - /** - * Creates a value object representing the given boolean value. - */ - public static IValue create(boolean value) { - return create(value ? 1 : 0); - } - - /** - * Creates a value representing the given template parameter - * in the given template. - */ - public static IValue create(ICPPTemplateDefinition template, ICPPTemplateNonTypeParameter tntp) { - EvalBinding eval = new EvalBinding(tntp, null, template); - return new Value(null, eval); - } - - /** - * Create a value wrapping the given evaluation. - */ - public static IValue create(ICPPEvaluation eval) { - return new Value(null, eval); - } - - public static IValue evaluateBinaryExpression(final int op, final long v1, final long v2) { - Number val = applyBinaryOperator(op, v1, v2); - if (val != null && val != VALUE_CANNOT_BE_DETERMINED) - return create(val.longValue()); - return UNKNOWN; - } - - public static IValue evaluateUnaryExpression(final int unaryOp, final long value) { - Number val = applyUnaryOperator(unaryOp, value); - if (val != null && val != VALUE_CANNOT_BE_DETERMINED) - return create(val.longValue()); - return UNKNOWN; - } - - public static IValue evaluateUnaryTypeIdExpression(int operator, IType type, IASTNode point) { - Number val = applyUnaryTypeIdOperator(operator, type, point); - if (val != null && val != VALUE_CANNOT_BE_DETERMINED) - return create(val.longValue()); - return UNKNOWN; - } - - public static IValue evaluateBinaryTypeIdExpression(IASTBinaryTypeIdExpression.Operator operator, - IType type1, IType type2, IASTNode point) { - Number val = applyBinaryTypeIdOperator(operator, type1, type2, point); - if (val != null && val != VALUE_CANNOT_BE_DETERMINED) - return create(val.longValue()); - return UNKNOWN; - } - - public static IValue incrementedValue(IValue value, int increment) { - if (value == UNKNOWN) - return UNKNOWN; - Long val = value.numericalValue(); - if (val != null) { - return create(val.longValue() + increment); - } - ICPPEvaluation arg1 = value.getEvaluation(); - EvalFixed arg2 = new EvalFixed(CPPBasicType.INT, ValueCategory.PRVALUE, create(increment)); - return create(new EvalBinary(IASTBinaryExpression.op_plus, arg1, arg2, arg1.getTemplateDefinition())); - } - - private static Number applyUnaryTypeIdOperator(int operator, IType type, IASTNode point) { - switch (operator) { - case op_sizeof: - return getSize(type, point); - case op_alignof: - return getAlignment(type, point); - case op_typeid: - break; - case op_has_nothrow_copy: - break; // TODO(sprigogin): Implement - case op_has_nothrow_constructor: - break; // TODO(sprigogin): Implement - case op_has_trivial_assign: - break; // TODO(sprigogin): Implement - case op_has_trivial_constructor: - break; // TODO(sprigogin): Implement - case op_has_trivial_copy: - return !(type instanceof ICPPClassType) || - TypeTraits.hasTrivialCopyCtor((ICPPClassType) type, point) ? 1 : 0; - case op_has_trivial_destructor: - break; // TODO(sprigogin): Implement - case op_has_virtual_destructor: - break; // TODO(sprigogin): Implement - case op_is_abstract: - return type instanceof ICPPClassType && - TypeTraits.isAbstract((ICPPClassType) type, point) ? 1 : 0; - case op_is_class: - return type instanceof ICompositeType && - ((ICompositeType) type).getKey() != ICompositeType.k_union ? 1 : 0; - case op_is_empty: - return TypeTraits.isEmpty(type, point) ? 1 : 0; - case op_is_enum: - return type instanceof IEnumeration ? 1 : 0; - case op_is_final: - return type instanceof ICPPClassType && ((ICPPClassType) type).isFinal() ? 1 : 0; - case op_is_literal_type: - break; // TODO(sprigogin): Implement - case op_is_pod: - return TypeTraits.isPOD(type, point) ? 1 : 0; - case op_is_polymorphic: - return type instanceof ICPPClassType && - TypeTraits.isPolymorphic((ICPPClassType) type, point) ? 1 : 0; - case op_is_standard_layout: - return TypeTraits.isStandardLayout(type, point) ? 1 : 0; - case op_is_trivial: - return type instanceof ICPPClassType && - TypeTraits.isTrivial((ICPPClassType) type, point) ? 1 : 0; - case op_is_trivially_copyable: - return TypeTraits.isTriviallyCopyable(type, point) ? 1 : 0; - case op_is_union: - return type instanceof ICompositeType && - ((ICompositeType) type).getKey() == ICompositeType.k_union ? 1 : 0; - case op_typeof: - break; - } - return VALUE_CANNOT_BE_DETERMINED; - } - - public static Number applyBinaryTypeIdOperator(IASTBinaryTypeIdExpression.Operator operator, - IType type1, IType type2, IASTNode point) { - switch (operator) { - case __is_base_of: - type1 = SemanticUtil.getNestedType(type1, TDEF); - type2 = SemanticUtil.getNestedType(type2, TDEF); - if (type1 instanceof ICPPClassType && type2 instanceof ICPPClassType && - (type1.isSameType(type2) || - ClassTypeHelper.isSubclass((ICPPClassType) type2, (ICPPClassType) type1, point))) { - return 1; - } - return 0; - case __is_trivially_assignable: - return VALUE_CANNOT_BE_DETERMINED; // TODO: Implement. - } - return VALUE_CANNOT_BE_DETERMINED; - } - - private static Number getAlignment(IType type, IASTNode point) { - SizeAndAlignment sizeAndAlignment = SizeofCalculator.getSizeAndAlignment(type, point); - if (sizeAndAlignment == null) - return VALUE_CANNOT_BE_DETERMINED; - return sizeAndAlignment.alignment; - } - - private static Number getSize(IType type, IASTNode point) { - SizeAndAlignment sizeAndAlignment = SizeofCalculator.getSizeAndAlignment(type, point); - if (sizeAndAlignment == null) - return VALUE_CANNOT_BE_DETERMINED; - return sizeAndAlignment.size; - } - - /** - * Tests whether the value is a template parameter (or a parameter pack). - * - * @return the parameter id of the parameter, or -1 if it is not a template - * parameter. - */ - public static int isTemplateParameter(IValue tval) { - ICPPEvaluation eval = tval.getEvaluation(); - if (eval instanceof EvalBinding) { - return ((EvalBinding) eval).getTemplateParameterID(); - } - return -1; - } - - /** - * Tests whether the value references some template parameter. - */ - public static boolean referencesTemplateParameter(IValue tval) { - ICPPEvaluation eval = tval.getEvaluation(); - if (eval == null) - return false; - return eval.referencesTemplateParameter(); - } - - /** - * Tests whether the value depends on a template parameter. - */ - public static boolean isDependentValue(IValue nonTypeValue) { - if (nonTypeValue == null) - return false; - ICPPEvaluation eval = nonTypeValue.getEvaluation(); - return eval != null && eval.isValueDependent(); - } - - /** - * Creates the value for an expression. - */ - public static IValue create(IASTExpression expr) { - Number val= evaluate(expr); - if (val == VALUE_CANNOT_BE_DETERMINED) - return UNKNOWN; - if (val != null) - return create(val.longValue()); - - if (expr instanceof ICPPASTInitializerClause) { - ICPPEvaluation evaluation = ((ICPPASTInitializerClause) expr).getEvaluation(); - return evaluation.getValue(expr); - } - return UNKNOWN; - } - - /** - * Creates a value off its canonical representation. - */ - public static IValue fromInternalRepresentation(ICPPEvaluation evaluation) { - return new Value(null, evaluation); - } - - /** - * Creates a unique value needed during template instantiation. - */ - public static IValue unique() { - StringBuilder buf= new StringBuilder(10); - buf.append(UNIQUE_CHAR); - buf.append(++sUnique); - return new Value(CharArrayUtils.extractChars(buf), null); - } - - /** - * Computes the canonical representation of the value of the expression. - * Returns a {@code Number} for numerical values or {@code null}, otherwise. - * @throws UnknownValueException - */ - private static Number evaluate(IASTExpression exp) { - if (exp == null) - return VALUE_CANNOT_BE_DETERMINED; - - if (exp instanceof IASTArraySubscriptExpression) { - return VALUE_CANNOT_BE_DETERMINED; - } - if (exp instanceof IASTBinaryExpression) { - return evaluateBinaryExpression((IASTBinaryExpression) exp); - } - if (exp instanceof IASTCastExpression) { // must be ahead of unary - return evaluate(((IASTCastExpression) exp).getOperand()); - } - if (exp instanceof IASTUnaryExpression) { - return evaluateUnaryExpression((IASTUnaryExpression) exp); - } - if (exp instanceof IASTConditionalExpression) { - IASTConditionalExpression cexpr= (IASTConditionalExpression) exp; - Number v= evaluate(cexpr.getLogicalConditionExpression()); - if (v == null || v == VALUE_CANNOT_BE_DETERMINED) - return v; - if (v.longValue() == 0) { - return evaluate(cexpr.getNegativeResultExpression()); - } - final IASTExpression pe = cexpr.getPositiveResultExpression(); - if (pe == null) // gnu-extension allows to omit the positive expression. - return v; - return evaluate(pe); - } - if (exp instanceof IASTIdExpression) { - IBinding b= ((IASTIdExpression) exp).getName().resolvePreBinding(); - return evaluateBinding(b); - } - if (exp instanceof IASTLiteralExpression) { - IASTLiteralExpression litEx= (IASTLiteralExpression) exp; - switch (litEx.getKind()) { - case IASTLiteralExpression.lk_false: - case IASTLiteralExpression.lk_nullptr: - return Long.valueOf(0); - case IASTLiteralExpression.lk_true: - return Long.valueOf(1); - case IASTLiteralExpression.lk_integer_constant: - try { - return ExpressionEvaluator.getNumber(litEx.getValue()); - } catch (EvalException e) { - return VALUE_CANNOT_BE_DETERMINED; - } - case IASTLiteralExpression.lk_char_constant: - try { - final char[] image= litEx.getValue(); - if (image.length > 1 && image[0] == 'L') - return ExpressionEvaluator.getChar(image, 2); - return ExpressionEvaluator.getChar(image, 1); - } catch (EvalException e) { - return VALUE_CANNOT_BE_DETERMINED; - } - } - } - if (exp instanceof IASTTypeIdExpression) { - IASTTypeIdExpression typeIdExp = (IASTTypeIdExpression) exp; - ASTTranslationUnit ast = (ASTTranslationUnit) exp.getTranslationUnit(); - final IType type = ast.createType(typeIdExp.getTypeId()); - if (type instanceof ICPPUnknownType) - return null; - return applyUnaryTypeIdOperator(typeIdExp.getOperator(), type, exp); - } - if (exp instanceof IASTBinaryTypeIdExpression) { - IASTBinaryTypeIdExpression typeIdExp = (IASTBinaryTypeIdExpression) exp; - ASTTranslationUnit ast = (ASTTranslationUnit) exp.getTranslationUnit(); - IType t1= ast.createType(typeIdExp.getOperand1()); - IType t2= ast.createType(typeIdExp.getOperand2()); - if (CPPTemplates.isDependentType(t1) || CPPTemplates.isDependentType(t2)) - return null; - return applyBinaryTypeIdOperator(typeIdExp.getOperator(), t1, t2, exp); - } - if (exp instanceof IASTFunctionCallExpression || exp instanceof ICPPASTSimpleTypeConstructorExpression) { - return null; // The value will be obtained from the evaluation. - } - return VALUE_CANNOT_BE_DETERMINED; - } - - /** - * Extract a value off a binding. - */ - private static Number evaluateBinding(IBinding b) { - if (b instanceof IType) { - return VALUE_CANNOT_BE_DETERMINED; - } - if (b instanceof ICPPTemplateNonTypeParameter) { - return null; - } - - if (b instanceof ICPPUnknownBinding) { - return null; - } - - IValue value= null; - if (b instanceof IVariable) { - value= ((IVariable) b).getInitialValue(); - } else if (b instanceof IEnumerator) { - value= ((IEnumerator) b).getValue(); - } - if (value != null && value != Value.UNKNOWN) { - return value.numericalValue(); - } - - return VALUE_CANNOT_BE_DETERMINED; - } - - private static Number evaluateUnaryExpression(IASTUnaryExpression exp) { - final int unaryOp= exp.getOperator(); - - if (unaryOp == IASTUnaryExpression.op_sizeof) { - final IASTExpression operand = exp.getOperand(); - if (operand != null) { - IType type = operand.getExpressionType(); - if (type instanceof ICPPUnknownType) - return null; - ASTTranslationUnit ast = (ASTTranslationUnit) exp.getTranslationUnit(); - SizeofCalculator calculator = ast.getSizeofCalculator(); - SizeAndAlignment info = calculator.sizeAndAlignment(type); - if (info != null) - return info.size; - } - return VALUE_CANNOT_BE_DETERMINED; - } - - if (unaryOp == IASTUnaryExpression.op_amper || unaryOp == IASTUnaryExpression.op_star || - unaryOp == IASTUnaryExpression.op_sizeofParameterPack) { - return VALUE_CANNOT_BE_DETERMINED; - } - - final Number value= evaluate(exp.getOperand()); - if (value == null || value == VALUE_CANNOT_BE_DETERMINED) - return value; - return applyUnaryOperator(unaryOp, value.longValue()); - } - - private static Number applyUnaryOperator(final int unaryOp, final long value) { - switch (unaryOp) { - case IASTUnaryExpression.op_bracketedPrimary: - case IASTUnaryExpression.op_plus: - return value; - } - - switch (unaryOp) { - case IASTUnaryExpression.op_prefixIncr: - case IASTUnaryExpression.op_postFixIncr: - return value + 1; - case IASTUnaryExpression.op_prefixDecr: - case IASTUnaryExpression.op_postFixDecr: - return value - 1; - case IASTUnaryExpression.op_minus: - return -value; - case IASTUnaryExpression.op_tilde: - return ~value; - case IASTUnaryExpression.op_not: - return value == 0 ? 1 : 0; - } - return VALUE_CANNOT_BE_DETERMINED; - } - - private static Number evaluateBinaryExpression(IASTBinaryExpression exp) { - final int op= exp.getOperator(); - switch (op) { - case IASTBinaryExpression.op_equals: - if (exp.getOperand1().equals(exp.getOperand2())) - return Long.valueOf(1); - break; - case IASTBinaryExpression.op_notequals: - if (exp.getOperand1().equals(exp.getOperand2())) - return Long.valueOf(0); - break; - } - - final Number o1= evaluate(exp.getOperand1()); - if (o1 == null || o1 == VALUE_CANNOT_BE_DETERMINED) - return o1; - final Number o2= evaluate(exp.getOperand2()); - if (o2 == null || o2 == VALUE_CANNOT_BE_DETERMINED) - return o2; - - return applyBinaryOperator(op, o1.longValue(), o2.longValue()); - } - - private static Number applyBinaryOperator(final int op, final long v1, final long v2) { - switch (op) { - case IASTBinaryExpression.op_multiply: - return v1 * v2; - case IASTBinaryExpression.op_divide: - if (v2 == 0) - return VALUE_CANNOT_BE_DETERMINED; - return v1 / v2; - case IASTBinaryExpression.op_modulo: - if (v2 == 0) - return VALUE_CANNOT_BE_DETERMINED; - return v1 % v2; - case IASTBinaryExpression.op_plus: - return v1 + v2; - case IASTBinaryExpression.op_minus: - return v1 - v2; - case IASTBinaryExpression.op_shiftLeft: - return v1 << v2; - case IASTBinaryExpression.op_shiftRight: - return v1 >> v2; - case IASTBinaryExpression.op_lessThan: - return v1 < v2 ? 1 : 0; - case IASTBinaryExpression.op_greaterThan: - return v1 > v2 ? 1 : 0; - case IASTBinaryExpression.op_lessEqual: - return v1 <= v2 ? 1 : 0; - case IASTBinaryExpression.op_greaterEqual: - return v1 >= v2 ? 1 : 0; - case IASTBinaryExpression.op_binaryAnd: - return v1 & v2; - case IASTBinaryExpression.op_binaryXor: - return v1 ^ v2; - case IASTBinaryExpression.op_binaryOr: - return v1 | v2; - case IASTBinaryExpression.op_logicalAnd: - return v1 != 0 && v2 != 0 ? 1 : 0; - case IASTBinaryExpression.op_logicalOr: - return v1 != 0 || v2 != 0 ? 1 : 0; - case IASTBinaryExpression.op_equals: - return v1 == v2 ? 1 : 0; - case IASTBinaryExpression.op_notequals: - return v1 != v2 ? 1 : 0; - case IASTBinaryExpression.op_max: - return Math.max(v1, v2); - case IASTBinaryExpression.op_min: - return Math.min(v1, v2); - } - return VALUE_CANNOT_BE_DETERMINED; - } - - /** - * Parses a long, returns null if not possible - */ - private static Long parseLong(char[] value) { - final long maxvalue= Long.MAX_VALUE / 10; - final int len= value.length; - boolean negative= false; - long result = 0; - int i= 0; - - if (len > 0 && value[0] == '-') { - negative = true; - i++; - } - if (i == len) - return null; - - for (; i < len; i++) { - if (result > maxvalue) - return null; - - final int digit= (value[i] - '0'); - if (digit < 0 || digit > 9) - return null; - result= result * 10 + digit; - } - return negative ? -result : result; - } - - /** - * Converts long to a char array - */ - private static char[] toCharArray(long value) { - StringBuilder buf= new StringBuilder(); - buf.append(value); - return CharArrayUtils.extractChars(buf); - } -} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java new file mode 100644 index 00000000000..191f78b15a0 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java @@ -0,0 +1,586 @@ +/******************************************************************************* + * Copyright (c) 2008, 2014 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser; + +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_alignof; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_nothrow_constructor; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_nothrow_copy; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_assign; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_constructor; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_copy; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_destructor; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_virtual_destructor; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_abstract; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_class; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_empty; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_enum; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_final; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_literal_type; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_pod; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_polymorphic; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_standard_layout; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivial; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivially_copyable; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_union; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeof; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeid; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; + +import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; +import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; +import org.eclipse.cdt.core.dom.ast.IASTBinaryTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTCastExpression; +import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.ICompositeType; +import org.eclipse.cdt.core.dom.ast.IEnumeration; +import org.eclipse.cdt.core.dom.ast.IEnumerator; +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.ICPPASTSimpleTypeConstructorExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; +import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluationOwner; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeTraits; +import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator; +import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException; + +public class ValueFactory { + /** + * Creates the value for an expression. + */ + public static IValue create(IASTExpression expr) { + IValue val= evaluate(expr); + if (val != null) { + return val; + } + + if (expr instanceof ICPPEvaluationOwner) { + ICPPEvaluation evaluation = ((ICPPEvaluationOwner) expr).getEvaluation(); + return evaluation.getValue(expr); + } + return IntegralValue.UNKNOWN; + } + + public static IValue evaluateUnaryExpression(final int unaryOp, final IValue value) { + IValue val = applyUnaryOperator(unaryOp, value); + if (isInvalidValue(val)) + return IntegralValue.UNKNOWN; + return val; + } + + public static IValue evaluateBinaryExpression(final int op, final IValue v1, final IValue v2) { + if(v1 instanceof FloatingPointValue && v2 instanceof FloatingPointValue) { + FloatingPointValue fv1 = (FloatingPointValue)v1; + FloatingPointValue fv2 = (FloatingPointValue)v2; + return applyBinaryOperator(op, fv1.numberValue().doubleValue(), fv2.numberValue().doubleValue()); + } else if(v1 instanceof FloatingPointValue && v2 instanceof IntegralValue) { + FloatingPointValue fv1 = (FloatingPointValue)v1; + IntegralValue iv2 = (IntegralValue)v2; + return applyBinaryOperator(op, fv1.numberValue().doubleValue(), iv2.numberValue().doubleValue()); + } else if(v1 instanceof IntegralValue && v2 instanceof FloatingPointValue) { + IntegralValue iv1 = (IntegralValue)v1; + FloatingPointValue fv2 = (FloatingPointValue)v2; + return applyBinaryOperator(op, iv1.numberValue().doubleValue(), fv2.numberValue().doubleValue()); + } else if(v1 instanceof IntegralValue && v2 instanceof IntegralValue) { + IntegralValue iv1 = (IntegralValue)v1; + IntegralValue iv2 = (IntegralValue)v2; + return applyBinaryOperator(op, iv1.numberValue().longValue(), iv2.numberValue().longValue()); + } + return IntegralValue.UNKNOWN; + } + + private static IValue applyBinaryOperator(final int op, final double v1, final double v2) { + Double doubleValue = null; + Long longValue = null; + + switch (op) { + case IASTBinaryExpression.op_multiply: + doubleValue = v1 * v2; + break; + case IASTBinaryExpression.op_divide: + if (v2 != 0) { + doubleValue = v1 / v2; + } + break; + case IASTBinaryExpression.op_plus: + doubleValue = v1 + v2; + break; + case IASTBinaryExpression.op_minus: + doubleValue = v1 - v2; + break; + case IASTBinaryExpression.op_lessThan: + longValue = v1 < v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_greaterThan: + longValue = v1 > v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_lessEqual: + longValue = v1 <= v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_greaterEqual: + longValue = v1 >= v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_logicalAnd: + longValue = v1 != 0 && v2 != 0 ? 1l : 0l; + break; + case IASTBinaryExpression.op_logicalOr: + longValue = v1 != 0 || v2 != 0 ? 1l : 0l; + break; + case IASTBinaryExpression.op_equals: + longValue = v1 == v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_notequals: + longValue = v1 != v2 ? 1l : 0l; + break; + } + + if(doubleValue != null) { + return FloatingPointValue.create(doubleValue); + } else if(longValue != null) { + return IntegralValue.create(longValue); + } else { + return IntegralValue.UNKNOWN; + } + } + + private static IntegralValue applyBinaryOperator(final int op, final long v1, final long v2) { + Long value = null; + switch (op) { + case IASTBinaryExpression.op_multiply: + value = v1 * v2; + break; + case IASTBinaryExpression.op_divide: + if (v2 != 0) { + value = v1 / v2; + } + break; + case IASTBinaryExpression.op_modulo: + if (v2 != 0) { + value = v1 % v2; + } + break; + case IASTBinaryExpression.op_plus: + value = v1 + v2; + break; + case IASTBinaryExpression.op_minus: + value = v1 - v2; + break; + case IASTBinaryExpression.op_shiftLeft: + value = v1 << v2; + break; + case IASTBinaryExpression.op_shiftRight: + value = v1 >> v2; + break; + case IASTBinaryExpression.op_lessThan: + value = v1 < v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_greaterThan: + value = v1 > v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_lessEqual: + value = v1 <= v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_greaterEqual: + value = v1 >= v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_binaryAnd: + value = v1 & v2; + break; + case IASTBinaryExpression.op_binaryXor: + value = v1 ^ v2; + break; + case IASTBinaryExpression.op_binaryOr: + value = v1 | v2; + break; + case IASTBinaryExpression.op_logicalAnd: + value = v1 != 0 && v2 != 0 ? 1l : 0l; + break; + case IASTBinaryExpression.op_logicalOr: + value = v1 != 0 || v2 != 0 ? 1l : 0l; + break; + case IASTBinaryExpression.op_equals: + value = v1 == v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_notequals: + value = v1 != v2 ? 1l : 0l; + break; + case IASTBinaryExpression.op_max: + value = Math.max(v1, v2); + break; + case IASTBinaryExpression.op_min: + value = Math.min(v1, v2); + break; + } + + if(value != null) { + return IntegralValue.create(value); + } else { + return IntegralValue.UNKNOWN; + } + } + + public static IValue evaluateUnaryTypeIdExpression(int operator, IType type, IASTNode point) { + IValue val = applyUnaryTypeIdOperator(operator, type, point); + if (isInvalidValue(val)) + return IntegralValue.UNKNOWN; + return val; + } + + public static IValue evaluateBinaryTypeIdExpression(IASTBinaryTypeIdExpression.Operator operator, + IType type1, IType type2, IASTNode point) { + IValue val = applyBinaryTypeIdOperator(operator, type1, type2, point); + if (isInvalidValue(val)) + return IntegralValue.UNKNOWN; + return val; + } + + /** + * Computes the canonical representation of the value of the expression. + */ + private static IValue evaluate(IASTExpression exp) { + if (exp == null) + return IntegralValue.UNKNOWN; + + if (exp instanceof IASTArraySubscriptExpression) { + return IntegralValue.UNKNOWN; + } + if (exp instanceof IASTBinaryExpression) { + return evaluateBinaryExpression((IASTBinaryExpression) exp); + } + if (exp instanceof IASTCastExpression) { // must be ahead of unary + return evaluate(((IASTCastExpression) exp).getOperand()); + } + if (exp instanceof IASTUnaryExpression) { + return evaluateUnaryExpression((IASTUnaryExpression) exp); + } + if (exp instanceof IASTConditionalExpression) { + IASTConditionalExpression cexpr= (IASTConditionalExpression) exp; + IValue v= evaluate(cexpr.getLogicalConditionExpression()); + if (isInvalidValue(v) || v.numberValue() == null) + return v; + if (v.numberValue().longValue() == 0) { + return evaluate(cexpr.getNegativeResultExpression()); + } + final IASTExpression pe = cexpr.getPositiveResultExpression(); + if (pe == null) // gnu-extension allows to omit the positive expression. + return v; + return evaluate(pe); + } + if (exp instanceof IASTIdExpression) { + IBinding b= ((IASTIdExpression) exp).getName().resolvePreBinding(); + return evaluateBinding(b); + } + if (exp instanceof IASTLiteralExpression) { + IASTLiteralExpression litEx= (IASTLiteralExpression) exp; + switch (litEx.getKind()) { + case IASTLiteralExpression.lk_false: + case IASTLiteralExpression.lk_nullptr: + return IntegralValue.create(0); + case IASTLiteralExpression.lk_true: + return IntegralValue.create(1); + case IASTLiteralExpression.lk_integer_constant: + try { + return IntegralValue.create(ExpressionEvaluator.getNumber(litEx.getValue())); + } catch (EvalException e) { + return IntegralValue.UNKNOWN; + } + case IASTLiteralExpression.lk_char_constant: + try { + final char[] image= litEx.getValue(); + if (image.length > 1 && image[0] == 'L') + return IntegralValue.create(ExpressionEvaluator.getChar(image, 2)); + return IntegralValue.create(ExpressionEvaluator.getChar(image, 1)); + } catch (EvalException e) { + return IntegralValue.UNKNOWN; + } + case IASTLiteralExpression.lk_float_constant: + return FloatingPointValue.create(litEx.getValue()); + case IASTLiteralExpression.lk_string_literal: + return CStringValue.create(litEx.getValue()); + } + } + + if (exp instanceof IASTTypeIdExpression) { + IASTTypeIdExpression typeIdExp = (IASTTypeIdExpression) exp; + ASTTranslationUnit ast = (ASTTranslationUnit) exp.getTranslationUnit(); + final IType type = ast.createType(typeIdExp.getTypeId()); + if (type instanceof ICPPUnknownType) + return null; + return applyUnaryTypeIdOperator(typeIdExp.getOperator(), type, exp); + } + if (exp instanceof IASTBinaryTypeIdExpression) { + IASTBinaryTypeIdExpression typeIdExp = (IASTBinaryTypeIdExpression) exp; + ASTTranslationUnit ast = (ASTTranslationUnit) exp.getTranslationUnit(); + IType t1= ast.createType(typeIdExp.getOperand1()); + IType t2= ast.createType(typeIdExp.getOperand2()); + if (CPPTemplates.isDependentType(t1) || CPPTemplates.isDependentType(t2)) + return null; + return applyBinaryTypeIdOperator(typeIdExp.getOperator(), t1, t2, exp); + } + if (exp instanceof IASTFunctionCallExpression || exp instanceof ICPPASTSimpleTypeConstructorExpression) { + return null; // The value will be obtained from the evaluation. + } + return IntegralValue.UNKNOWN; + } + + /** + * Extract a value off a binding. + */ + private static IValue evaluateBinding(IBinding b) { + if (b instanceof IType) { + return IntegralValue.UNKNOWN; + } + if (b instanceof ICPPTemplateNonTypeParameter) { + return null; + } + + if (b instanceof ICPPUnknownBinding) { + return null; + } + + IValue value= null; + if (b instanceof IVariable) { + value= ((IVariable) b).getInitialValue(); + } else if (b instanceof IEnumerator) { + value= ((IEnumerator) b).getValue(); + } + if (isInvalidValue(value)) { + return IntegralValue.UNKNOWN; + } + return value; + } + + private static IValue applyUnaryTypeIdOperator(int operator, IType type, IASTNode point) { + switch (operator) { + case op_sizeof: + return getSize(type, point); + case op_alignof: + return getAlignment(type, point); + case op_typeid: + break; + case op_has_nothrow_copy: + break; // TODO(sprigogin): Implement + case op_has_nothrow_constructor: + break; // TODO(sprigogin): Implement + case op_has_trivial_assign: + break; // TODO(sprigogin): Implement + case op_has_trivial_constructor: + break; // TODO(sprigogin): Implement + case op_has_trivial_copy: + return IntegralValue.create(!(type instanceof ICPPClassType) || + TypeTraits.hasTrivialCopyCtor((ICPPClassType) type, point) ? 1 : 0); + case op_has_trivial_destructor: + break; // TODO(sprigogin): Implement + case op_has_virtual_destructor: + break; // TODO(sprigogin): Implement + case op_is_abstract: + return IntegralValue.create(type instanceof ICPPClassType && + TypeTraits.isAbstract((ICPPClassType) type, point) ? 1 : 0); + case op_is_class: + return IntegralValue.create(type instanceof ICompositeType && + ((ICompositeType) type).getKey() != ICompositeType.k_union ? 1 : 0); + case op_is_empty: + return IntegralValue.create(TypeTraits.isEmpty(type, point) ? 1 : 0); + case op_is_enum: + return IntegralValue.create(type instanceof IEnumeration ? 1 : 0); + case op_is_final: + return IntegralValue.create(type instanceof ICPPClassType && ((ICPPClassType) type).isFinal() ? 1 : 0); + case op_is_literal_type: + break; // TODO(sprigogin): Implement + case op_is_pod: + return IntegralValue.create(TypeTraits.isPOD(type, point) ? 1 : 0); + case op_is_polymorphic: + return IntegralValue.create(type instanceof ICPPClassType && + TypeTraits.isPolymorphic((ICPPClassType) type, point) ? 1 : 0); + case op_is_standard_layout: + return IntegralValue.create(TypeTraits.isStandardLayout(type, point) ? 1 : 0); + case op_is_trivial: + return IntegralValue.create(type instanceof ICPPClassType && + TypeTraits.isTrivial((ICPPClassType) type, point) ? 1 : 0); + case op_is_trivially_copyable: + return IntegralValue.create(TypeTraits.isTriviallyCopyable(type, point) ? 1 : 0); + case op_is_union: + return IntegralValue.create(type instanceof ICompositeType && + ((ICompositeType) type).getKey() == ICompositeType.k_union ? 1 : 0); + case op_typeof: + break; + } + return IntegralValue.UNKNOWN; + } + + private static IValue getAlignment(IType type, IASTNode point) { + SizeAndAlignment sizeAndAlignment = SizeofCalculator.getSizeAndAlignment(type, point); + if (sizeAndAlignment == null) + return IntegralValue.UNKNOWN; + return IntegralValue.create(sizeAndAlignment.alignment); + } + + private static IValue getSize(IType type, IASTNode point) { + SizeAndAlignment sizeAndAlignment = SizeofCalculator.getSizeAndAlignment(type, point); + if (sizeAndAlignment == null) + return IntegralValue.UNKNOWN; + return IntegralValue.create(sizeAndAlignment.size); + } + + private static IValue evaluateUnaryExpression(IASTUnaryExpression exp) { + final int unaryOp= exp.getOperator(); + + if (unaryOp == IASTUnaryExpression.op_sizeof) { + final IASTExpression operand = exp.getOperand(); + if (operand != null) { + IType type = operand.getExpressionType(); + if (type instanceof ICPPUnknownType) + return null; + ASTTranslationUnit ast = (ASTTranslationUnit) exp.getTranslationUnit(); + SizeofCalculator calculator = ast.getSizeofCalculator(); + SizeAndAlignment info = calculator.sizeAndAlignment(type); + if (info != null) + return IntegralValue.create(info.size); + } + return IntegralValue.UNKNOWN; + } + + if (unaryOp == IASTUnaryExpression.op_amper || unaryOp == IASTUnaryExpression.op_star || + unaryOp == IASTUnaryExpression.op_sizeofParameterPack) { + return IntegralValue.UNKNOWN; + } + + final IValue value= evaluate(exp.getOperand()); + if (isInvalidValue(value)) + return value; + if (isDeferredValue(value)) + return null; // the value will be computed using the evaluation + return applyUnaryOperator(unaryOp, value); + } + + private static IValue applyUnaryOperator(final int unaryOp, final IValue value) { + if(isInvalidValue(value) || value.numberValue() == null) { + return IntegralValue.UNKNOWN; + } + + if(!(value instanceof IntegralValue) && !(value instanceof FloatingPointValue)) { + return IntegralValue.UNKNOWN; + } + + switch (unaryOp) { + case IASTUnaryExpression.op_bracketedPrimary: + case IASTUnaryExpression.op_plus: + return value; + case IASTUnaryExpression.op_prefixIncr: + case IASTUnaryExpression.op_postFixIncr: + if(value instanceof IntegralValue) { + return IntegralValue.create(value.numberValue().longValue() + 1); + } else { + FloatingPointValue fpv = (FloatingPointValue) value; + return FloatingPointValue.create(fpv.numberValue().doubleValue() + 1); + } + case IASTUnaryExpression.op_prefixDecr: + case IASTUnaryExpression.op_postFixDecr: + if(value instanceof IntegralValue) { + return IntegralValue.create(value.numberValue().longValue() - 1); + } else { + FloatingPointValue fpv = (FloatingPointValue) value; + return FloatingPointValue.create(fpv.numberValue().doubleValue() - 1); + } + case IASTUnaryExpression.op_minus: + if(value instanceof IntegralValue) { + return IntegralValue.create(-value.numberValue().longValue()); + } else { + FloatingPointValue fpv = (FloatingPointValue) value; + return FloatingPointValue.create(-fpv.numberValue().doubleValue()); + } + case IASTUnaryExpression.op_tilde: + if(value instanceof IntegralValue) { + return IntegralValue.create(~value.numberValue().longValue()); + } else { + return IntegralValue.UNKNOWN; + } + case IASTUnaryExpression.op_not: + if(value instanceof IntegralValue) { + Long num = value.numberValue().longValue(); + return IntegralValue.create(num == 0 ? 1 : 0); + } else { + FloatingPointValue fpv = (FloatingPointValue) value; + Double num = fpv.numberValue().doubleValue(); + return IntegralValue.create(num == 0 ? 1 : 0); + } + } + return IntegralValue.UNKNOWN; + } + + private static IValue evaluateBinaryExpression(IASTBinaryExpression exp) { + final int op= exp.getOperator(); + + // Optimization: if the operator is == or != and the AST nodes + // themselves are equal, we know the answer without having to + // do any evaluation. + if (op == IASTBinaryExpression.op_equals && exp.getOperand1().equals(exp.getOperand2())) { + return IntegralValue.create(true); + } + if (op == IASTBinaryExpression.op_notequals && exp.getOperand1().equals(exp.getOperand2())) { + return IntegralValue.create(false); + } + + final IValue o1= evaluate(exp.getOperand1()); + if (isInvalidValue(o1)) + return o1; + final IValue o2= evaluate(exp.getOperand2()); + if (isInvalidValue(o2)) + return o2; + if (isDeferredValue(o1) || isDeferredValue(o2)) + return null; // the value will be computed using the evaluation + return evaluateBinaryExpression(op, o1, o2); + } + + private static IValue applyBinaryTypeIdOperator(IASTBinaryTypeIdExpression.Operator operator, + IType type1, IType type2, IASTNode point) { + switch (operator) { + case __is_base_of: + type1 = SemanticUtil.getNestedType(type1, TDEF); + type2 = SemanticUtil.getNestedType(type2, TDEF); + if (type1 instanceof ICPPClassType && type2 instanceof ICPPClassType && + (type1.isSameType(type2) || + ClassTypeHelper.isSubclass((ICPPClassType) type2, (ICPPClassType) type1, point))) { + return IntegralValue.create(1); + } + return IntegralValue.create(0); + case __is_trivially_assignable: + return IntegralValue.UNKNOWN; // TODO: Implement. + } + return IntegralValue.UNKNOWN; + } + + private static boolean isInvalidValue(IValue value) { + return value == null || value == IntegralValue.UNKNOWN || value == IntegralValue.ERROR; + } + + private static boolean isDeferredValue(IValue value) { + return value instanceof IntegralValue && ((IntegralValue) value).numberValue() == null; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java index a250bb1cc6c..67e91f651f7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java @@ -51,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluationOwner; import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; /** @@ -213,7 +214,7 @@ public abstract class VariableReadWriteFlags { private IType getArgumentType(IASTInitializerClause argument) { if (argument instanceof ICPPASTInitializerClause) { - return ((ICPPASTInitializerClause) argument).getEvaluation().getType(argument); + return ((ICPPEvaluationOwner) argument).getEvaluation().getType(argument); } else if (argument instanceof IASTExpression) { return ((IASTExpression) argument).getExpressionType(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java index 00e6ee9280e..7550b418eec 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java @@ -23,13 +23,14 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.core.runtime.CoreException; public class CArrayType implements ICArrayType, ITypeContainer, ISerializableType { IType type; private IASTExpression sizeExpression; - private IValue value= Value.NOT_INITIALIZED; + private IValue value= IntegralValue.NOT_INITIALIZED; private boolean isConst; private boolean isVolatile; private boolean isRestrict; @@ -130,18 +131,18 @@ public class CArrayType implements ICArrayType, ITypeContainer, ISerializableTyp @Override public IValue getSize() { - if (value != Value.NOT_INITIALIZED) + if (value != IntegralValue.NOT_INITIALIZED) return value; if (sizeExpression == null) return value= null; - return value= Value.create(sizeExpression); + return value= ValueFactory.create(sizeExpression); } @Override public boolean hasSize() { - return value == Value.NOT_INITIALIZED ? sizeExpression != null : value != null; + return value == IntegralValue.NOT_INITIALIZED ? sizeExpression != null : value != null; } @Override @@ -175,9 +176,9 @@ public class CArrayType implements ICArrayType, ITypeContainer, ISerializableTyp val= getSize(); if (val != null) { firstBytes |= ITypeMarshalBuffer.FLAG6; - Long num= val.numericalValue(); + Number num= val.numberValue(); if (num != null) { - nval= num; + nval= num.longValue(); if (nval >= 0) { firstBytes |= ITypeMarshalBuffer.FLAG7; } @@ -195,7 +196,7 @@ public class CArrayType implements ICArrayType, ITypeContainer, ISerializableTyp public static IType unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { IValue value= null; if ((firstBytes & ITypeMarshalBuffer.FLAG7) != 0) { - value = Value.create(buffer.getLong()); + value = IntegralValue.create(buffer.getLong()); } else if ((firstBytes & ITypeMarshalBuffer.FLAG6) != 0) { value = buffer.unmarshalValue(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java index d77b1bd8c06..7626a524755 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java @@ -24,7 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.ASTEnumerator; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.core.runtime.PlatformObject; /** @@ -37,7 +37,7 @@ public class CEnumerator extends PlatformObject implements IEnumerator { } @Override public IValue getValue() { - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } @@ -99,7 +99,7 @@ public class CEnumerator extends PlatformObject implements IEnumerator { if (parent instanceof ASTEnumerator) return ((ASTEnumerator) parent).getIntegralValue(); - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariable.java index e5befc22180..04e46a43d22 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariable.java @@ -33,7 +33,8 @@ import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.core.runtime.PlatformObject; /** @@ -160,7 +161,7 @@ public class CVariable extends PlatformObject implements ICInternalBinding, IVar public IValue getInitialValue() { Set recursionProtectionSet = fInitialValueInProgress.get(); if (!recursionProtectionSet.add(this)) { - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } try { if (declarations != null) { @@ -186,11 +187,11 @@ public class CVariable extends PlatformObject implements ICInternalBinding, IVar final IASTInitializerClause initClause = ((IASTEqualsInitializer) init) .getInitializerClause(); if (initClause instanceof IASTExpression) { - return Value.create((IASTExpression) initClause); + return ValueFactory.create((IASTExpression) initClause); } } if (init != null) - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index d4ef6f3bb33..457db61227a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -110,7 +110,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.cdt.internal.core.parser.util.ContentAssistMatcherFactory; @@ -1746,9 +1746,9 @@ public class CVisitor extends ASTQueries { IType expressionType = expression.getExpressionType(); if (expressionType instanceof IBasicType) { - IValue value = Value.create(expression); - if (value != null && value.numericalValue() != null) { - return value.numericalValue().longValue() == 0; + IValue value = ValueFactory.create(expression); + if (value != null && value.numberValue() != null) { + return value.numberValue().longValue() == 0; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java index a635cb68824..249bd500c5c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java @@ -32,7 +32,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinary; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; public class CPPASTArraySubscriptExpression extends ASTNode - implements ICPPASTArraySubscriptExpression, IASTAmbiguityParent { + implements ICPPASTArraySubscriptExpression, IASTAmbiguityParent, ICPPEvaluationOwner { private ICPPASTExpression arrayExpression; private ICPPASTInitializerClause subscriptExp; private ICPPEvaluation evaluation; @@ -195,7 +195,10 @@ public class CPPASTArraySubscriptExpression extends ASTNode private ICPPEvaluation computeEvaluation() { if (arrayExpression == null || subscriptExp == null) return EvalFixed.INCOMPLETE; - return new EvalBinary(EvalBinary.op_arrayAccess, arrayExpression.getEvaluation(), subscriptExp.getEvaluation(), this); + return new EvalBinary(EvalBinary.op_arrayAccess, + ((ICPPEvaluationOwner)arrayExpression).getEvaluation(), + ((ICPPEvaluationOwner)subscriptExp).getEvaluation(), + this); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java index d8f02d2e798..56c9cdf45a0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java @@ -36,7 +36,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinary; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; -public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpression, IASTAmbiguityParent { +public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpression, IASTAmbiguityParent, ICPPEvaluationOwner { private int fOperator; private ICPPASTExpression fOperand1; private ICPPASTInitializerClause fOperand2; @@ -280,7 +280,9 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr if (fOperand1 == null || fOperand2 == null) return EvalFixed.INCOMPLETE; - return new EvalBinary(fOperator, fOperand1.getEvaluation(), fOperand2.getEvaluation(), this); + ICPPEvaluation eval1 = ((ICPPEvaluationOwner)fOperand1).getEvaluation(); + ICPPEvaluation eval2 = ((ICPPEvaluationOwner)fOperand2).getEvaluation(); + return new EvalBinary(fOperator, eval1, eval2, this); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryTypeIdExpression.java index 1b6bfc1409c..e3291a6237b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryTypeIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryTypeIdExpression.java @@ -25,7 +25,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinaryTypeId; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; -public class CPPASTBinaryTypeIdExpression extends ASTNode implements ICPPASTExpression, IASTBinaryTypeIdExpression { +public class CPPASTBinaryTypeIdExpression extends ASTNode implements ICPPASTExpression, IASTBinaryTypeIdExpression, ICPPEvaluationOwner { private Operator fOperator; private IASTTypeId fOperand1; private IASTTypeId fOperand2; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBreakStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBreakStatement.java index f4caf315d17..a3dbf875836 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBreakStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBreakStatement.java @@ -13,11 +13,12 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTBreakStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecBreak; /** * @author jcamelon */ -public class CPPASTBreakStatement extends CPPASTAttributeOwner implements IASTBreakStatement { +public class CPPASTBreakStatement extends CPPASTAttributeOwner implements IASTBreakStatement, ICPPExecutionOwner { @Override public boolean accept(ASTVisitor action) { if (action.shouldVisitStatements) { @@ -50,4 +51,9 @@ public class CPPASTBreakStatement extends CPPASTAttributeOwner implements IASTBr CPPASTBreakStatement copy = new CPPASTBreakStatement(); return copy(copy, style); } + + @Override + public ICPPExecution getExecution() { + return new ExecBreak(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCaseStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCaseStatement.java index 30c00324059..8e5d4e63654 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCaseStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCaseStatement.java @@ -15,11 +15,12 @@ import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTCaseStatement; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecCase; /** * @author jcamelon */ -public class CPPASTCaseStatement extends CPPASTAttributeOwner implements IASTCaseStatement { +public class CPPASTCaseStatement extends CPPASTAttributeOwner implements IASTCaseStatement, ICPPExecutionOwner { private IASTExpression expression; public CPPASTCaseStatement() { @@ -89,4 +90,11 @@ public class CPPASTCaseStatement extends CPPASTAttributeOwner implements IASTCas } super.replace(child, other); } + + @Override + public ICPPExecution getExecution() { + ICPPEvaluationOwner caseExpr = (ICPPEvaluationOwner)getExpression(); + ICPPEvaluation caseExprEval = caseExpr.getEvaluation(); + return new ExecCase(caseExprEval); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCastExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCastExpression.java index 6a10a4600bf..1b631469581 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCastExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCastExpression.java @@ -33,7 +33,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; /** * Cast expression for C++ */ -public class CPPASTCastExpression extends ASTNode implements ICPPASTCastExpression, IASTAmbiguityParent { +public class CPPASTCastExpression extends ASTNode implements ICPPASTCastExpression, IASTAmbiguityParent, ICPPEvaluationOwner { private int fOperator; private ICPPASTExpression fOperand; private IASTTypeId fTypeId; @@ -167,7 +167,7 @@ public class CPPASTCastExpression extends ASTNode implements ICPPASTCastExpressi if (type == null || type instanceof IProblemType) return EvalFixed.INCOMPLETE; - return new EvalTypeId(type, this, fOperand.getEvaluation()); + return new EvalTypeId(type, this, false, ((ICPPEvaluationOwner)fOperand).getEvaluation()); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatement.java index 0e0c620f32d..44ede731045 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatement.java @@ -20,11 +20,12 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.DestructorCallCollector; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecCompoundStatement; /** * @author jcamelon */ -public class CPPASTCompoundStatement extends CPPASTAttributeOwner implements ICPPASTCompoundStatement { +public class CPPASTCompoundStatement extends CPPASTAttributeOwner implements ICPPASTCompoundStatement, ICPPExecutionOwner { private IASTStatement[] statements = new IASTStatement[2]; private ICPPScope scope; private IASTImplicitDestructorName[] fImplicitDestructorNames; @@ -120,4 +121,9 @@ public class CPPASTCompoundStatement extends CPPASTAttributeOwner implements ICP } super.replace(child, other); } + + @Override + public ICPPExecution getExecution() { + return new ExecCompoundStatement(this.statements); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatementExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatementExpression.java index e8b4e26ab70..31ef2253352 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatementExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatementExpression.java @@ -24,18 +24,21 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.DestructorCallCollector; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalCompound; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalCompoundStatementExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; /** * Gnu-extension: ({ ... }) */ public class CPPASTCompoundStatementExpression extends ASTNode - implements IGNUASTCompoundStatementExpression, ICPPASTExpression { + implements IGNUASTCompoundStatementExpression, ICPPASTExpression, ICPPEvaluationOwner { private IASTCompoundStatement fStatement; private ICPPEvaluation fEval; private IASTImplicitDestructorName[] fImplicitDestructorNames; - + + public CPPASTCompoundStatementExpression() { + } + public CPPASTCompoundStatementExpression(IASTCompoundStatement statement) { setCompoundStatement(statement); } @@ -73,11 +76,11 @@ public class CPPASTCompoundStatementExpression extends ASTNode if (fStatement != null) { IASTStatement[] statements = fStatement.getStatements(); if (statements.length > 0) { - IASTStatement lastStatement = statements[statements.length - 1]; - if (lastStatement instanceof IASTExpressionStatement) { - ICPPASTExpression expression = - (ICPPASTExpression) ((IASTExpressionStatement) lastStatement).getExpression(); - fEval= new EvalCompound(expression.getEvaluation(), this); + IASTStatement st = statements[statements.length - 1]; + if (st instanceof IASTExpressionStatement) { + IASTExpressionStatement exprStmt = (IASTExpressionStatement)st; + ICPPEvaluationOwner evalOwner = (ICPPEvaluationOwner)exprStmt.getExpression(); + fEval= new EvalCompoundStatementExpression(evalOwner.getEvaluation(), this); } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java index f102522918a..7e3b93f90f8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java @@ -29,7 +29,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalConditional; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; public class CPPASTConditionalExpression extends ASTNode - implements IASTConditionalExpression, ICPPASTExpression, IASTAmbiguityParent { + implements IASTConditionalExpression, ICPPASTExpression, IASTAmbiguityParent, ICPPEvaluationOwner { private ICPPASTExpression fCondition; private ICPPASTExpression fPositive; private ICPPASTExpression fNegative; @@ -179,9 +179,10 @@ public class CPPASTConditionalExpression extends ASTNode if (fCondition == null || fNegative == null) { fEval= EvalFixed.INCOMPLETE; } else { - final ICPPEvaluation condEval = fCondition.getEvaluation(); - final ICPPEvaluation posEval = fPositive == null ? null : fPositive.getEvaluation(); - fEval= new EvalConditional(condEval, posEval, fNegative.getEvaluation(), + final ICPPEvaluation condEval = ((ICPPEvaluationOwner)fCondition).getEvaluation(); + final ICPPEvaluation posEval = fPositive == null ? null : ((ICPPEvaluationOwner)fPositive).getEvaluation(); + final ICPPEvaluation negEval = ((ICPPEvaluationOwner)fNegative).getEvaluation(); + fEval= new EvalConditional(condEval, posEval, negEval, isThrowExpression(fPositive), isThrowExpression(fNegative), this); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTContinueStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTContinueStatement.java index 4cf6161fb6f..6b258042425 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTContinueStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTContinueStatement.java @@ -13,11 +13,12 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTContinueStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecContinue; /** * @author jcamelon */ -public class CPPASTContinueStatement extends CPPASTAttributeOwner implements IASTContinueStatement { +public class CPPASTContinueStatement extends CPPASTAttributeOwner implements IASTContinueStatement, ICPPExecutionOwner { @Override public boolean accept(ASTVisitor action) { if (action.shouldVisitStatements) { @@ -50,4 +51,9 @@ public class CPPASTContinueStatement extends CPPASTAttributeOwner implements IAS CPPASTContinueStatement copy = new CPPASTContinueStatement(); return copy(copy, style); } + + @Override + public ICPPExecution getExecution() { + return new ExecContinue(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarationStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarationStatement.java index f5cf34d49f9..c9eb6c186ee 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarationStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarationStatement.java @@ -20,12 +20,13 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecDeclarationStatement; /** * @author jcamelon */ public class CPPASTDeclarationStatement extends ASTNode - implements IASTDeclarationStatement, IASTAmbiguityParent { + implements IASTDeclarationStatement, IASTAmbiguityParent, ICPPExecutionOwner { private IASTDeclaration declaration; public CPPASTDeclarationStatement() { @@ -116,4 +117,13 @@ public class CPPASTDeclarationStatement extends ASTNode // Declaration statements don't have attributes. throw new UnsupportedOperationException(); } + + @Override + public ICPPExecution getExecution() { + if(declaration instanceof ICPPExecutionOwner) { + ICPPExecutionOwner execOwner = (ICPPExecutionOwner)declaration; + return new ExecDeclarationStatement(execOwner.getExecution()); + } + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java index 8efc68cccea..56fd5c7654f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java @@ -32,18 +32,22 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecDeclarator; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecIncomplete; /** * C++ specific declarator. */ public class CPPASTDeclarator extends CPPASTAttributeOwner implements ICPPASTDeclarator, - IASTImplicitNameOwner { + IASTImplicitNameOwner, ICPPExecutionOwner { private IASTInitializer initializer; private IASTName name; private IASTImplicitName[] implicitNames; @@ -303,4 +307,18 @@ public class CPPASTDeclarator extends CPPASTAttributeOwner implements ICPPASTDec } super.replace(child, other); } + + @Override + public ICPPExecution getExecution() { + final ICPPBinding binding = (ICPPBinding)getName().resolveBinding(); + ICPPEvaluation initializerEval = null; + if(binding instanceof CPPVariable) { + CPPVariable variable = (CPPVariable)binding; + initializerEval = variable.getInitializerEvaluation(); + } + if(initializerEval == EvalFixed.INCOMPLETE) { + return ExecIncomplete.INSTANCE; + } + return new ExecDeclarator(binding, initializerEval); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDecltypeSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDecltypeSpecifier.java index 05237448d18..b47625fccdd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDecltypeSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDecltypeSpecifier.java @@ -57,7 +57,7 @@ public class CPPASTDecltypeSpecifier extends ASTNode StringBuilder buffer = new StringBuilder(); buffer.append(Keywords.cDECLTYPE); buffer.append(Keywords.cpLPAREN); - buffer.append(fDecltypeExpression.getEvaluation().getSignature()); + buffer.append(((ICPPEvaluationOwner)fDecltypeExpression).getEvaluation().getSignature()); buffer.append(Keywords.cpRPAREN); final int len = buffer.length(); fSignature = new char[len]; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDefaultStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDefaultStatement.java index bce65e915fb..f984556242f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDefaultStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDefaultStatement.java @@ -13,11 +13,12 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecDefault; /** * @author jcamelon */ -public class CPPASTDefaultStatement extends CPPASTAttributeOwner implements IASTDefaultStatement { +public class CPPASTDefaultStatement extends CPPASTAttributeOwner implements IASTDefaultStatement, ICPPExecutionOwner { @Override public boolean accept(ASTVisitor action) { if (action.shouldVisitStatements) { @@ -50,4 +51,9 @@ public class CPPASTDefaultStatement extends CPPASTAttributeOwner implements IAST CPPASTDefaultStatement copy = new CPPASTDefaultStatement(); return copy(copy, style); } + + @Override + public ICPPExecution getExecution() { + return new ExecDefault(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java index c99d081058a..1f7f714f09d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java @@ -27,14 +27,14 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.DestructorCallCollector; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; -public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpression, IASTAmbiguityParent { - private static final ICPPEvaluation EVALUATION = new EvalFixed(CPPSemantics.VOID_TYPE, PRVALUE, Value.UNKNOWN); +public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpression, IASTAmbiguityParent, ICPPEvaluationOwner { + private static final ICPPEvaluation EVALUATION = new EvalFixed(CPPSemantics.VOID_TYPE, PRVALUE, IntegralValue.UNKNOWN); private IASTExpression operand; private boolean isGlobal; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDesignatedInitializer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDesignatedInitializer.java index 89f9216cd14..2fdd659bfeb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDesignatedInitializer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDesignatedInitializer.java @@ -23,7 +23,7 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; * Implementation for designated initializers. */ public class CPPASTDesignatedInitializer extends ASTNode - implements ICPPASTDesignatedInitializer, IASTAmbiguityParent { + implements ICPPASTDesignatedInitializer, IASTAmbiguityParent, ICPPEvaluationOwner { private ICPPASTInitializerClause rhs; private ICPPASTDesignator[] designators = ICPPASTDesignator.EMPTY_ARRAY; private int designatorsPos; @@ -83,7 +83,7 @@ public class CPPASTDesignatedInitializer extends ASTNode @Override public ICPPEvaluation getEvaluation() { - return rhs.getEvaluation(); + return ((ICPPEvaluationOwner)rhs).getEvaluation(); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDoStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDoStatement.java index beb893cc698..66dba60031d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDoStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDoStatement.java @@ -16,11 +16,13 @@ import org.eclipse.cdt.core.dom.ast.IASTDoStatement; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecDo; /** * @author jcamelon */ -public class CPPASTDoStatement extends CPPASTAttributeOwner implements IASTDoStatement { +public class CPPASTDoStatement extends CPPASTAttributeOwner implements IASTDoStatement, ICPPExecutionOwner { private IASTStatement body; private IASTExpression condition; @@ -115,4 +117,12 @@ public class CPPASTDoStatement extends CPPASTAttributeOwner implements IASTDoSta } super.replace(child, other); } + + @Override + public ICPPExecution getExecution() { + ICPPEvaluationOwner conditionExpr = (ICPPEvaluationOwner)getCondition(); + ICPPEvaluation conditionEval = conditionExpr.getEvaluation(); + ICPPExecution bodyExec = EvalUtil.getExecutionFromStatement(getBody()); + return new ExecDo(conditionEval, bodyExec); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java index 4e6a40dd94b..e991b21a3ae 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java @@ -21,7 +21,6 @@ import org.eclipse.cdt.core.dom.ast.IASTImplicitDestructorName; import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IType; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpressionList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.parser.util.ArrayUtil; @@ -31,7 +30,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.DestructorCallColl import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalComma; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; -public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionList, IASTAmbiguityParent { +public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionList, IASTAmbiguityParent, ICPPEvaluationOwner { private IASTExpression[] expressions = new IASTExpression[2]; /** @@ -188,7 +187,7 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi ICPPEvaluation[] evals= new ICPPEvaluation[exprs.length]; for (int i = 0; i < evals.length; i++) { - evals[i]= ((ICPPASTExpression) exprs[i]).getEvaluation(); + evals[i]= ((ICPPEvaluationOwner) exprs[i]).getEvaluation(); } return new EvalComma(evals, this); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionStatement.java index 29bfa156585..af053f48919 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionStatement.java @@ -15,11 +15,12 @@ import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecExpressionStatement; /** * @author jcamelon */ -public class CPPASTExpressionStatement extends CPPASTAttributeOwner implements IASTExpressionStatement { +public class CPPASTExpressionStatement extends CPPASTAttributeOwner implements IASTExpressionStatement, ICPPExecutionOwner { private IASTExpression expression; public CPPASTExpressionStatement() { @@ -89,4 +90,11 @@ public class CPPASTExpressionStatement extends CPPASTAttributeOwner implements I } super.replace(child, other); } + + @Override + public ICPPExecution getExecution() { + ICPPEvaluationOwner evalOwner = (ICPPEvaluationOwner)getExpression(); + ICPPEvaluation exprEval = evalOwner.getEvaluation(); + return new ExecExpressionStatement(exprEval); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java index 66b34fa9d98..8b3732a15e6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java @@ -15,6 +15,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ; import java.util.ArrayList; import java.util.Arrays; @@ -36,7 +37,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +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.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; @@ -50,20 +53,21 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.DestructorCallColl import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalID; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalMemberAccess; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; public class CPPASTFieldReference extends ASTNode - implements ICPPASTFieldReference, IASTAmbiguityParent, ICPPASTCompletionContext { - private boolean fIsTemplate; - private boolean fIsDeref; - private ICPPASTExpression fOwner; - private IASTName fName; - private IASTImplicitName[] fImplicitNames; + implements ICPPASTFieldReference, IASTAmbiguityParent, ICPPASTCompletionContext, ICPPEvaluationOwner { + private boolean fIsTemplate; + private boolean fIsDeref; + private ICPPASTExpression fOwner; + private IASTName fName; + private IASTImplicitName[] fImplicitNames; private ICPPEvaluation fEvaluation; private IASTImplicitDestructorName[] fImplicitDestructorNames; - public CPPASTFieldReference() { + public CPPASTFieldReference() { } - + public CPPASTFieldReference(IASTName name, IASTExpression owner) { setFieldName(name); setFieldOwner(owner); @@ -86,57 +90,57 @@ public class CPPASTFieldReference extends ASTNode @Override public boolean isTemplate() { - return fIsTemplate; - } + return fIsTemplate; + } - @Override + @Override public void setIsTemplate(boolean value) { - assertNotFrozen(); - fIsTemplate = value; - } + assertNotFrozen(); + fIsTemplate = value; + } - @Override + @Override public ICPPASTExpression getFieldOwner() { - return fOwner; - } + return fOwner; + } - @Override + @Override public void setFieldOwner(IASTExpression expression) { - assertNotFrozen(); - fOwner = (ICPPASTExpression) expression; - if (expression != null) { + assertNotFrozen(); + fOwner = (ICPPASTExpression) expression; + if (expression != null) { expression.setParent(this); expression.setPropertyInParent(FIELD_OWNER); } - } + } - @Override + @Override public IASTName getFieldName() { - return fName; - } + return fName; + } - @Override + @Override public void setFieldName(IASTName name) { - assertNotFrozen(); - this.fName = name; - if (name != null) { + assertNotFrozen(); + this.fName = name; + if (name != null) { name.setParent(this); name.setPropertyInParent(FIELD_NAME); } - } + } - @Override + @Override public boolean isPointerDereference() { - return fIsDeref; - } + return fIsDeref; + } - @Override + @Override public void setIsPointerDereference(boolean value) { - assertNotFrozen(); - fIsDeref = value; - } - - @Override + assertNotFrozen(); + fIsDeref = value; + } + + @Override public IASTImplicitName[] getImplicitNames() { if (fImplicitNames == null) { if (!fIsDeref) @@ -147,24 +151,25 @@ public class CPPASTFieldReference extends ASTNode EvalMemberAccess.getFieldOwnerType(fOwner.getExpressionType(), fIsDeref, this, functionBindings, false); if (functionBindings.isEmpty()) return fImplicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; - + // Create a name to wrap each binding fImplicitNames = new IASTImplicitName[functionBindings.size()]; - int i= -1; + int i = -1; for (ICPPFunction op : functionBindings) { if (op != null && !(op instanceof CPPImplicitFunction)) { - CPPASTImplicitName operatorName = new CPPASTImplicitName(OverloadableOperator.ARROW, this); + CPPASTImplicitName operatorName = new CPPASTImplicitName(OverloadableOperator.ARROW, + this); operatorName.setBinding(op); operatorName.computeOperatorOffsets(fOwner, true); fImplicitNames[++i] = operatorName; } } - fImplicitNames= ArrayUtil.trimAt(IASTImplicitName.class, fImplicitNames, i); + fImplicitNames = ArrayUtil.trimAt(IASTImplicitName.class, fImplicitNames, i); } - + return fImplicitNames; } - + @Override public IASTImplicitDestructorName[] getImplicitDestructorNames() { if (fImplicitDestructorNames == null) { @@ -174,41 +179,47 @@ public class CPPASTFieldReference extends ASTNode return fImplicitDestructorNames; } - @Override + @Override public boolean accept(ASTVisitor action) { - if (action.shouldVisitExpressions) { - switch (action.visit(this)) { - case ASTVisitor.PROCESS_ABORT: return false; - case ASTVisitor.PROCESS_SKIP: return true; - default: break; - } + if (action.shouldVisitExpressions) { + switch (action.visit(this)) { + case ASTVisitor.PROCESS_ABORT: + return false; + case ASTVisitor.PROCESS_SKIP: + return true; + default: + break; + } } - - if (fOwner != null && !fOwner.accept(action)) - return false; - - if (action.shouldVisitImplicitNames) { - for (IASTImplicitName name : getImplicitNames()) { - if (!name.accept(action)) - return false; - } - } - - if (fName != null && !fName.accept(action)) - return false; - if (action.shouldVisitImplicitDestructorNames && !acceptByNodes(getImplicitDestructorNames(), action)) - return false; + if (fOwner != null && !fOwner.accept(action)) + return false; - if (action.shouldVisitExpressions) { - switch (action.leave(this)) { - case ASTVisitor.PROCESS_ABORT: return false; - case ASTVisitor.PROCESS_SKIP: return true; - default: break; - } + if (action.shouldVisitImplicitNames) { + for (IASTImplicitName name : getImplicitNames()) { + if (!name.accept(action)) + return false; + } } - return true; - } + + if (fName != null && !fName.accept(action)) + return false; + + if (action.shouldVisitImplicitDestructorNames && !acceptByNodes(getImplicitDestructorNames(), action)) + return false; + + if (action.shouldVisitExpressions) { + switch (action.leave(this)) { + case ASTVisitor.PROCESS_ABORT: + return false; + case ASTVisitor.PROCESS_SKIP: + return true; + default: + break; + } + } + return true; + } @Override public int getRoleForName(IASTName n) { @@ -217,14 +228,14 @@ public class CPPASTFieldReference extends ASTNode return r_unclear; } - @Override + @Override public void replace(IASTNode child, IASTNode other) { - if (child == fOwner) { - other.setPropertyInParent(child.getPropertyInParent()); - other.setParent(child.getParent()); - fOwner = (ICPPASTExpression) other; - } - } + if (child == fOwner) { + other.setPropertyInParent(child.getPropertyInParent()); + other.setParent(child.getParent()); + fOwner = (ICPPASTExpression) other; + } + } @Override public IBinding[] findBindings(IASTName n, boolean isPrefix, String[] namespaces) { @@ -237,39 +248,40 @@ public class CPPASTFieldReference extends ASTNode if (i != j) bindings[j] = binding; j++; + } } - } if (j < bindings.length) return Arrays.copyOfRange(bindings, 0, j); return bindings; } - + @Override public IBinding[] findBindings(IASTName n, boolean isPrefix) { return findBindings(n, isPrefix, null); } - - /** - * For a pointer dereference expression e1->e2, return the type that e1 ultimately evaluates to - * after chaining overloaded class member access operators operator->() calls. - */ - @Override + + /** + * For a pointer dereference expression e1->e2, return the type that e1 + * ultimately evaluates to after chaining overloaded class member access + * operators operator->() calls. + */ + @Override public IType getFieldOwnerType() { - return EvalMemberAccess.getFieldOwnerType(fOwner.getExpressionType(), fIsDeref, this, null, true); - } - + return EvalMemberAccess.getFieldOwnerType(fOwner.getExpressionType(), fIsDeref, this, null, true); + } + @Override public ICPPEvaluation getEvaluation() { if (fEvaluation == null) { - fEvaluation= createEvaluation(); + fEvaluation = createEvaluation(); } return fEvaluation; } - + private ICPPEvaluation createEvaluation() { - ICPPEvaluation ownerEval = fOwner.getEvaluation(); + ICPPEvaluation ownerEval = ((ICPPEvaluationOwner)fOwner).getEvaluation(); if (!ownerEval.isTypeDependent()) { IType ownerType= EvalMemberAccess.getFieldOwnerType(ownerEval.getType(this), fIsDeref, this, null, false); if (ownerType != null) { @@ -277,10 +289,11 @@ public class CPPASTFieldReference extends ASTNode if (binding instanceof CPPFunctionSet) binding= fName.resolveBinding(); - if (binding instanceof IProblemBinding || binding instanceof IType || binding instanceof ICPPConstructor) + if (binding instanceof IProblemBinding || binding instanceof IType || binding instanceof ICPPConstructor) { return EvalFixed.INCOMPLETE; + } - return new EvalMemberAccess(ownerType, ownerEval.getValueCategory(this), binding, fIsDeref, this); + return new EvalMemberAccess(ownerType, ownerEval.getValueCategory(this), binding, ownerEval, fIsDeref, this); } } @@ -306,12 +319,31 @@ public class CPPASTFieldReference extends ASTNode } return new EvalID(ownerEval, qualifier, fName.getSimpleID(), false, true, fIsDeref, args, this); } + + public static int getFieldPosition(ICPPField field) { + final ICPPClassType ownerType = field.getClassOwner(); + final ICPPClassType[] baseClasses = ClassTypeHelper.getAllBases(ownerType, null); + int baseFields = 0; + for(ICPPClassType baseClass : baseClasses) { + baseFields += ClassTypeHelper.getDeclaredFields(baseClass, null).length; + } + return baseFields + field.getFieldPosition(); + } + + public static int getFieldPosition(IBinding binding, IType ownerType) { + final IType nestedType = SemanticUtil.getNestedType(ownerType, ALLCVQ); + if(nestedType instanceof ICPPClassType && binding instanceof ICPPField) { + final ICPPField field = (ICPPField)binding; + return getFieldPosition(field); + } + return -1; + } @Override public IType getExpressionType() { return getEvaluation().getType(this); } - + @Override public boolean isLValue() { return getValueCategory() == LVALUE; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTForStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTForStatement.java index e395d42039a..839d32b7506 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTForStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTForStatement.java @@ -22,11 +22,14 @@ import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.DestructorCallCollector; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecFor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSimpleDeclaration; /** * For statement in C++ */ -public class CPPASTForStatement extends CPPASTAttributeOwner implements ICPPASTForStatement { +public class CPPASTForStatement extends CPPASTAttributeOwner implements ICPPASTForStatement, ICPPExecutionOwner { private IScope fScope; private IASTStatement fInit; @@ -222,4 +225,17 @@ public class CPPASTForStatement extends CPPASTAttributeOwner implements ICPPASTF public IASTDeclaration getConditionDeclaration() { return fCondDeclaration; } + + @Override + public ICPPExecution getExecution() { + ICPPExecution initializerExec = EvalUtil.getExecutionFromStatement(getInitializerStatement()); + ICPPEvaluationOwner conditionExpr = (ICPPEvaluationOwner)getConditionExpression(); + ICPPExecutionOwner conditionDecl = (ICPPExecutionOwner)getConditionDeclaration(); + ICPPEvaluation conditionExprEval = conditionExpr != null ? conditionExpr.getEvaluation() : null; + ExecSimpleDeclaration conditionDeclExec = conditionDecl != null ? (ExecSimpleDeclaration)conditionDecl.getExecution() : null; + ICPPEvaluationOwner iterationExpr = (ICPPEvaluationOwner)getIterationExpression(); + ICPPEvaluation iterationEval = iterationExpr != null ? iterationExpr.getEvaluation() : null; + ICPPExecution bodyExec = EvalUtil.getExecutionFromStatement(getBody()); + return new ExecFor(initializerExec, conditionExprEval, conditionDeclExec, iterationEval, bodyExec); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java index 721e2c0a6ba..d8b8060ccc6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java @@ -32,8 +32,8 @@ import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; @@ -49,7 +49,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.LookupData; public class CPPASTFunctionCallExpression extends ASTNode - implements ICPPASTFunctionCallExpression, IASTAmbiguityParent { + implements ICPPASTFunctionCallExpression, IASTAmbiguityParent, ICPPEvaluationOwner { private ICPPASTExpression fFunctionName; private IASTInitializerClause[] fArguments; @@ -281,11 +281,17 @@ public class CPPASTFunctionCallExpression extends ASTNode return conversion; ICPPEvaluation[] args= new ICPPEvaluation[fArguments.length + 1]; - args[0]= fFunctionName.getEvaluation(); + args[0]= ((ICPPEvaluationOwner)fFunctionName).getEvaluation(); for (int i = 1; i < args.length; i++) { - args[i]= ((ICPPASTInitializerClause) fArguments[i - 1]).getEvaluation(); + args[i]= ((ICPPEvaluationOwner) fArguments[i - 1]).getEvaluation(); } - return new EvalFunctionCall(args, this); + ICPPEvaluation fieldOwnerEval = null; + if (fFunctionName instanceof ICPPASTFieldReference) { + ICPPASTFieldReference fieldRef = (ICPPASTFieldReference)fFunctionName; + ICPPEvaluationOwner fieldOwner = (ICPPEvaluationOwner)fieldRef.getFieldOwner(); + fieldOwnerEval = fieldOwner.getEvaluation(); + } + return new EvalFunctionCall(args, fieldOwnerEval, this); } private ICPPEvaluation checkForExplicitTypeConversion() { @@ -295,9 +301,10 @@ public class CPPASTFunctionCallExpression extends ASTNode if (b instanceof IType) { ICPPEvaluation[] args= new ICPPEvaluation[fArguments.length]; for (int i = 0; i < args.length; i++) { - args[i]= ((ICPPASTInitializerClause) fArguments[i]).getEvaluation(); + args[i]= ((ICPPEvaluationOwner) fArguments[i]).getEvaluation(); } - return new EvalTypeId((IType) b, this, args); + + return new EvalTypeId((IType) b, this, false, args); } } return null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java index 6ecbf14c067..954624d7704 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java @@ -33,7 +33,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.FunctionSetType; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; public class CPPASTIdExpression extends ASTNode - implements IASTIdExpression, ICPPASTExpression, ICPPASTCompletionContext { + implements IASTIdExpression, ICPPASTExpression, ICPPASTCompletionContext, ICPPEvaluationOwner { private IASTName fName; private ICPPEvaluation fEvaluation; private IASTImplicitDestructorName[] fImplicitDestructorNames; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java index 00907fb8177..bd674c2e8d7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java @@ -20,11 +20,14 @@ import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecIf; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSimpleDeclaration; /** * If statement in C++ */ -public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIfStatement { +public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIfStatement, ICPPExecutionOwner { private IASTExpression condition; private IASTStatement thenClause; private IASTStatement elseClause; @@ -214,4 +217,15 @@ public class CPPASTIfStatement extends CPPASTAttributeOwner implements ICPPASTIf scope = new CPPBlockScope(this); return scope; } -} + + @Override + public ICPPExecution getExecution() { + ICPPEvaluationOwner conditionExpr = (ICPPEvaluationOwner)getConditionExpression(); + ICPPExecutionOwner conditionDecl = (ICPPExecutionOwner)getConditionDeclaration(); + ICPPEvaluation conditionExprEval = conditionExpr != null ? conditionExpr.getEvaluation() : null; + ExecSimpleDeclaration conditionDeclExec = conditionDecl != null ? (ExecSimpleDeclaration)conditionDecl.getExecution() : null; + ICPPExecution thenClauseExec = EvalUtil.getExecutionFromStatement(getThenClause()); + ICPPExecution elseClauseExec = getElseClause() != null ? EvalUtil.getExecutionFromStatement(getElseClause()) : null; + return new ExecIf(conditionExprEval, conditionDeclExec, thenClauseExec, elseClauseExec); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitializerList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitializerList.java index 74c968b550d..5ef4080ecd0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitializerList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitializerList.java @@ -27,7 +27,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalInitList; /** * e.g.: int a[]= {1,2,3}; */ -public class CPPASTInitializerList extends ASTNode implements ICPPASTInitializerList, IASTAmbiguityParent { +public class CPPASTInitializerList extends ASTNode implements ICPPASTInitializerList, IASTAmbiguityParent, ICPPEvaluationOwner { private static final ICPPASTInitializerClause[] NO_CLAUSES = {}; private ICPPASTInitializerClause[] initializers; private int initializersPos= -1; @@ -166,7 +166,8 @@ public class CPPASTInitializerList extends ASTNode implements ICPPASTInitializer final ICPPASTInitializerClause[] clauses = getClauses(); ICPPEvaluation[] evals= new ICPPEvaluation[clauses.length]; for (int i = 0; i < evals.length; i++) { - evals[i]= clauses[i].getEvaluation(); + ICPPEvaluationOwner clause = (ICPPEvaluationOwner)clauses[i]; + evals[i]= clause.getEvaluation(); } return new EvalInitList(evals, this); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLambdaExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLambdaExpression.java index a23f9da664e..f02f1316579 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLambdaExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLambdaExpression.java @@ -23,13 +23,13 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; /** * Implementation for lambda expressions. */ -public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpression { +public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpression, ICPPEvaluationOwner { private static final ICPPASTCapture[] NO_CAPTURES = {}; private CaptureDefault fCaptureDefault; @@ -208,7 +208,7 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr @Override public ICPPEvaluation getEvaluation() { if (fEvaluation == null) { - fEvaluation= new EvalFixed(new CPPClosureType(this), PRVALUE, Value.UNKNOWN); + fEvaluation= new EvalFixed(new CPPClosureType(this), PRVALUE, IntegralValue.UNKNOWN); } return fEvaluation; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java index c1acbd086c1..930e324f386 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java @@ -23,30 +23,36 @@ import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.dom.parser.CStringValue; +import org.eclipse.cdt.internal.core.dom.parser.FloatingPointValue; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFunctionCall; import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator; import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException; /** * Represents a C++ literal. */ -public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralExpression { - private static final EvalFixed EVAL_TRUE = new EvalFixed(CPPBasicType.BOOLEAN, PRVALUE, Value.create(1)); - private static final EvalFixed EVAL_FALSE = new EvalFixed(CPPBasicType.BOOLEAN, PRVALUE, Value.create(0)); - private static final EvalFixed EVAL_NULL_PTR = new EvalFixed(CPPBasicType.NULL_PTR, PRVALUE, Value.create(0)); +public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralExpression, ICPPEvaluationOwner { + private static final EvalFixed EVAL_TRUE = new EvalFixed(CPPBasicType.BOOLEAN, PRVALUE, IntegralValue.create(true)); + private static final EvalFixed EVAL_FALSE = new EvalFixed(CPPBasicType.BOOLEAN, PRVALUE, IntegralValue.create(false)); + private static final EvalFixed EVAL_NULL_PTR = new EvalFixed(CPPBasicType.NULL_PTR, PRVALUE, IntegralValue.create(0)); public static final CPPASTLiteralExpression INT_ZERO = new CPPASTLiteralExpression(lk_integer_constant, new char[] {'0'}); @@ -224,7 +230,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx } private int computeStringLiteralSize() { - int start = 0, end = fValue.length - 1; + int start = 0, end = fValue.length - 1 - getSuffix().length; boolean isRaw = false; // Skip past a prefix affecting the character type. @@ -289,7 +295,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx if (fStringLiteralSize == -1) { fStringLiteralSize = computeStringLiteralSize(); } - return Value.create(fStringLiteralSize); + return IntegralValue.create(fStringLiteralSize); } private IType getStringType() { @@ -643,49 +649,99 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx return fEvaluation; } - private ICPPEvaluation createEvaluation() { + private ICPPEvaluation createLiteralEvaluation() { switch (fKind) { - case lk_this: { - IScope scope = CPPVisitor.getContainingScope(this); - IType type= CPPVisitor.getImpliedObjectType(scope); - if (type == null) - return EvalFixed.INCOMPLETE; - return new EvalFixed(new CPPPointerType(type), PRVALUE, Value.UNKNOWN); - } - case lk_true: - return EVAL_TRUE; - case lk_false: - return EVAL_FALSE; - case lk_char_constant: - return new EvalFixed(getCharType(), PRVALUE, createCharValue()); - case lk_float_constant: - return new EvalFixed(classifyTypeOfFloatLiteral(), PRVALUE, Value.UNKNOWN); - case lk_integer_constant: - return new EvalFixed(classifyTypeOfIntLiteral(), PRVALUE, createIntValue()); - case lk_string_literal: - return new EvalFixed(getStringType(), LVALUE, Value.UNKNOWN); - case lk_nullptr: - return EVAL_NULL_PTR; + case lk_this: { + IScope scope = CPPVisitor.getContainingScope(this); + IType type= CPPVisitor.getImpliedObjectType(scope); + if (type == null) + return EvalFixed.INCOMPLETE; + return new EvalFixed(new CPPPointerType(type), PRVALUE, IntegralValue.THIS); + } + case lk_true: + return EVAL_TRUE; + case lk_false: + return EVAL_FALSE; + case lk_char_constant: + return new EvalFixed(getCharType(), PRVALUE, createCharValue()); + case lk_float_constant: + return new EvalFixed(classifyTypeOfFloatLiteral(), PRVALUE, FloatingPointValue.create(getValue())); + case lk_integer_constant: + return new EvalFixed(classifyTypeOfIntLiteral(), PRVALUE, createIntValue()); + case lk_string_literal: + return new EvalFixed(getStringType(), LVALUE, CStringValue.create(getValue())); + case lk_nullptr: + return EVAL_NULL_PTR; } - return EvalFixed.INCOMPLETE; + return EvalFixed.INCOMPLETE; + } + + private ICPPEvaluation createEvaluation() { + ICPPEvaluation literalEval = createLiteralEvaluation(); + + IBinding udlOperator = getUserDefinedLiteralOperator(); + if(udlOperator != null && literalEval != EvalFixed.INCOMPLETE) { + if(udlOperator instanceof ICPPFunction) { + ICPPFunction udlOpFunction = (ICPPFunction)udlOperator; + EvalBinding op = new EvalBinding(udlOpFunction, udlOpFunction.getType(), this); + ICPPEvaluation[] args = null; + + ICPPParameter params[] = udlOpFunction.getParameters(); + int paramCount = params.length; + if(paramCount == 0) { + // TODO: Support literal operator templates. + args = new ICPPEvaluation[]{op}; + } else if(paramCount == 1) { + //this means that we need to fall back to the raw literal operator + if(params[0].getType() instanceof IPointerType) { + char numValue[] = getValue(); + int numLen = numValue.length; + char strValue[] = new char[numLen + 2]; + strValue[0] = '"'; + strValue[numLen + 1] = '"'; + System.arraycopy(numValue, 0, strValue, 1, numLen); + + IType type = new CPPBasicType(Kind.eChar, 0, this); + type = new CPPQualifierType(type, true, false); + type = new CPPArrayType(type, IntegralValue.create(numLen+1)); + EvalFixed strEval = new EvalFixed(type, LVALUE, CStringValue.create(strValue)); + args = new ICPPEvaluation[]{op, strEval}; + } else { + args = new ICPPEvaluation[]{op, literalEval}; + } + } else if(paramCount == 2) { + IValue sizeValue = IntegralValue.create(computeStringLiteralSize() - 1); + EvalFixed literalSizeEval = new EvalFixed(CPPBasicType.INT, PRVALUE, sizeValue); + args = new ICPPEvaluation[]{op, literalEval, literalSizeEval}; + } + return new EvalFunctionCall(args, null, this); + } + } + + //has a user-defined literal suffix but didn't find a udl operator function => error + if(getSuffix().length > 0 && (getKind() == lk_string_literal || !fIsCompilerSuffix)) { + return EvalFixed.INCOMPLETE; + } + + return literalEval; } private IValue createCharValue() { try { final char[] image= getValue(); if (image.length > 1 && image[0] == 'L') - return Value.create(ExpressionEvaluator.getChar(image, 2)); - return Value.create(ExpressionEvaluator.getChar(image, 1)); + return IntegralValue.create(ExpressionEvaluator.getChar(image, 2)); + return IntegralValue.create(ExpressionEvaluator.getChar(image, 1)); } catch (EvalException e) { - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } private IValue createIntValue() { try { - return Value.create(ExpressionEvaluator.getNumber(getValue())); + return IntegralValue.create(ExpressionEvaluator.getNumber(getValue())); } catch (EvalException e) { - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNaryTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNaryTypeIdExpression.java index bf71ff981ae..6ca7310f85d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNaryTypeIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNaryTypeIdExpression.java @@ -18,7 +18,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; -public class CPPASTNaryTypeIdExpression extends ASTNode implements ICPPASTNaryTypeIdExpression { +public class CPPASTNaryTypeIdExpression extends ASTNode implements ICPPASTNaryTypeIdExpression, ICPPEvaluationOwner { private Operator fOperator; private ICPPASTTypeId[] fOperands; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java index dd6c496d7ca..412d80b1f34 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java @@ -32,7 +32,6 @@ import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; @@ -49,7 +48,7 @@ import org.eclipse.core.runtime.Assert; /** * Represents a new expression [expr.new]. */ -public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression, IASTAmbiguityParent { +public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression, IASTAmbiguityParent, ICPPEvaluationOwner { private IASTInitializerClause[] fPlacement; private IASTTypeId fTypeId; private IASTInitializer fInitializer; @@ -294,10 +293,10 @@ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression IASTInitializerClause[] args = ((ICPPASTConstructorInitializer) fInitializer).getArguments(); arguments= new ICPPEvaluation[args.length]; for (int i = 0; i < arguments.length; i++) { - arguments[i] = ((ICPPASTInitializerClause) args[i]).getEvaluation(); + arguments[i] = ((ICPPEvaluationOwner) args[i]).getEvaluation(); } } - fEvaluation = EvalTypeId.createForNewExpression(t, this, arguments); + fEvaluation = EvalTypeId.createForNewExpression(t, this, false, arguments); } return fEvaluation; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTPackExpansionExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTPackExpansionExpression.java index 540c5d886a5..3cec2e6e76f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTPackExpansionExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTPackExpansionExpression.java @@ -17,7 +17,6 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTImplicitDestructorName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IType; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPackExpansionExpression; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; @@ -26,7 +25,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalParameterPack; /** * Implementation of pack expansion expression. */ -public class CPPASTPackExpansionExpression extends ASTNode implements ICPPASTPackExpansionExpression, IASTAmbiguityParent { +public class CPPASTPackExpansionExpression extends ASTNode implements ICPPASTPackExpansionExpression, IASTAmbiguityParent, ICPPEvaluationOwner { private IASTExpression fPattern; private ICPPEvaluation fEvaluation; @@ -64,7 +63,7 @@ public class CPPASTPackExpansionExpression extends ASTNode implements ICPPASTPac @Override public ICPPEvaluation getEvaluation() { if (fEvaluation == null) { - fEvaluation = new EvalParameterPack(((ICPPASTExpression) fPattern).getEvaluation(), this); + fEvaluation = new EvalParameterPack(((ICPPEvaluationOwner) fPattern).getEvaluation(), this); } return fEvaluation; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTProblemExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTProblemExpression.java index f4b2277b87a..d54c1f87305 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTProblemExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTProblemExpression.java @@ -22,7 +22,7 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; -public class CPPASTProblemExpression extends CPPASTProblemOwner implements IASTProblemExpression, ICPPASTExpression { +public class CPPASTProblemExpression extends CPPASTProblemOwner implements IASTProblemExpression, ICPPASTExpression, ICPPEvaluationOwner { public CPPASTProblemExpression() { super(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTRangeBasedForStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTRangeBasedForStatement.java index 03267bde525..333deb501ac 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTRangeBasedForStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTRangeBasedForStatement.java @@ -23,20 +23,25 @@ import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IArrayType; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.DestructorCallCollector; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecRangeBasedFor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSimpleDeclaration; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; /** * Range based 'for' loop in C++. */ -public class CPPASTRangeBasedForStatement extends CPPASTAttributeOwner implements ICPPASTRangeBasedForStatement { +public class CPPASTRangeBasedForStatement extends CPPASTAttributeOwner implements ICPPASTRangeBasedForStatement, ICPPExecutionOwner { private IScope fScope; private IASTDeclaration fDeclaration; private IASTInitializerClause fInitClause; @@ -230,4 +235,23 @@ public class CPPASTRangeBasedForStatement extends CPPASTAttributeOwner implement } super.replace(child, other); } + + @Override + public ICPPExecution getExecution() { + ExecSimpleDeclaration declarationExec = (ExecSimpleDeclaration)((ICPPExecutionOwner)fDeclaration).getExecution(); + ICPPEvaluation initClauseEval = ((ICPPEvaluationOwner)fInitClause).getEvaluation(); + ICPPExecution bodyExec = EvalUtil.getExecutionFromStatement(fBody); + IASTImplicitName[] implicitNames = getImplicitNames(); + ICPPFunction begin = null; + ICPPFunction end = null; + if(implicitNames.length == 2) { + IBinding beginBinding = implicitNames[0].resolveBinding(); + IBinding endBinding = implicitNames[1].resolveBinding(); + if (beginBinding instanceof ICPPFunction && endBinding instanceof ICPPFunction) { + begin = (ICPPFunction)beginBinding; + end = (ICPPFunction)endBinding; + } + } + return new ExecRangeBasedFor(declarationExec, initClauseEval, begin, end, bodyExec); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTReturnStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTReturnStatement.java index 917ccd7e08a..2d8c5eb982c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTReturnStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTReturnStatement.java @@ -17,8 +17,10 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTReturnStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecIncomplete; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecReturn; -public class CPPASTReturnStatement extends CPPASTAttributeOwner implements IASTReturnStatement { +public class CPPASTReturnStatement extends CPPASTAttributeOwner implements IASTReturnStatement, ICPPExecutionOwner { private IASTInitializerClause retValue; public CPPASTReturnStatement() { @@ -101,4 +103,13 @@ public class CPPASTReturnStatement extends CPPASTAttributeOwner implements IASTR } super.replace(child, other); } + + @Override + public ICPPExecution getExecution() { + if(retValue instanceof ICPPEvaluationOwner) { + ICPPEvaluationOwner evalOwner = (ICPPEvaluationOwner)retValue; + return new ExecReturn(evalOwner.getEvaluation()); + } + return ExecIncomplete.INSTANCE; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleDeclaration.java index 544e4e059b7..d9dd40a1bca 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleDeclaration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleDeclaration.java @@ -18,11 +18,12 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSimpleDeclaration; /** * @author jcamelon */ -public class CPPASTSimpleDeclaration extends CPPASTAttributeOwner implements IASTSimpleDeclaration { +public class CPPASTSimpleDeclaration extends CPPASTAttributeOwner implements IASTSimpleDeclaration, ICPPExecutionOwner { private IASTDeclarator[] declarators; private int declaratorsPos = -1; private IASTDeclSpecifier declSpecifier; @@ -126,4 +127,13 @@ public class CPPASTSimpleDeclaration extends CPPASTAttributeOwner implements IAS } super.replace(child, other); } + + @Override + public ICPPExecution getExecution() { + ICPPExecution[] declaratorExecutions = new ICPPExecution[declarators.length]; + for(int i = 0; i < declarators.length; ++i) { + declaratorExecutions[i] = ((ICPPExecutionOwner)declarators[i]).getExecution(); + } + return new ExecSimpleDeclaration(declaratorExecutions); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleTypeConstructorExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleTypeConstructorExpression.java index 06cbcff3e0a..46fcca59007 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleTypeConstructorExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleTypeConstructorExpression.java @@ -18,12 +18,10 @@ import org.eclipse.cdt.core.dom.ast.IASTImplicitDestructorName; import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner; import org.eclipse.cdt.core.dom.ast.IASTInitializer; -import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; @@ -31,11 +29,12 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.DestructorCallCollector; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalConstructor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; public class CPPASTSimpleTypeConstructorExpression extends ASTNode - implements ICPPASTSimpleTypeConstructorExpression, IASTImplicitNameOwner { + implements ICPPASTSimpleTypeConstructorExpression, IASTImplicitNameOwner, ICPPEvaluationOwner { private ICPPASTDeclSpecifier fDeclSpec; private IASTInitializer fInitializer; private ICPPEvaluation fEvaluation; @@ -97,17 +96,10 @@ public class CPPASTSimpleTypeConstructorExpression extends ASTNode public ICPPEvaluation getEvaluation() { if (fEvaluation == null) { final IType type = CPPVisitor.createType(fDeclSpec); - ICPPEvaluation[] args= null; - if (fInitializer instanceof ICPPASTConstructorInitializer) { - IASTInitializerClause[] a = ((ICPPASTConstructorInitializer) fInitializer).getArguments(); - args= new ICPPEvaluation[a.length]; - for (int i = 0; i < a.length; i++) { - args[i]= ((ICPPASTInitializerClause) a[i]).getEvaluation(); - } - fEvaluation= new EvalTypeId(type, this, args); - } else if (fInitializer instanceof ICPPASTInitializerList) { - fEvaluation= new EvalTypeId(type, this, - ((ICPPASTInitializerList) fInitializer).getEvaluation()); + if (fInitializer instanceof ICPPASTConstructorInitializer || fInitializer instanceof ICPPASTInitializerList) { + boolean usesBracedInitList = (fInitializer instanceof ICPPASTInitializerList); + fEvaluation= new EvalTypeId(type, this, usesBracedInitList, + EvalConstructor.extractArguments(fInitializer)); } else { fEvaluation= EvalFixed.INCOMPLETE; } @@ -286,7 +278,7 @@ public class CPPASTSimpleTypeConstructorExpression extends ASTNode ICPPEvaluation eval = getEvaluation(); if (eval instanceof EvalTypeId) { ICPPFunction constructor = ((EvalTypeId) eval).getConstructor(this); - if (constructor != null) { + if (constructor != null && constructor != EvalTypeId.AGGREGATE_INITIALIZATION) { CPPASTImplicitName name = new CPPASTImplicitName(constructor.getNameCharArray(), this); name.setOffsetAndLength((ASTNode) fDeclSpec); name.setBinding(constructor); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSwitchStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSwitchStatement.java index 1e2c0ddc538..94ccf75be6e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSwitchStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSwitchStatement.java @@ -18,12 +18,16 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSwitchStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSimpleDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSwitch; /** * Switch statement in C++. */ -public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPASTSwitchStatement { +public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPASTSwitchStatement, ICPPExecutionOwner { private IScope scope; private IASTExpression controllerExpression; private IASTDeclaration controllerDeclaration; @@ -154,4 +158,25 @@ public class CPPASTSwitchStatement extends CPPASTAttributeOwner implements ICPPA scope = new CPPBlockScope(this); return scope; } + + @Override + public ICPPExecution getExecution() { + ICPPEvaluationOwner controllerExpr = (ICPPEvaluationOwner)getControllerExpression(); + ICPPExecutionOwner controllerDecl = (ICPPExecutionOwner)getControllerDeclaration(); + ICPPEvaluation controllerExprEval = controllerExpr != null ? controllerExpr.getEvaluation() : null; + ExecSimpleDeclaration controllerDeclExec = controllerDecl != null ? (ExecSimpleDeclaration)controllerDecl.getExecution() : null; + IASTStatement[] bodyStmts = null; + if(body instanceof ICPPASTCompoundStatement) { + ICPPASTCompoundStatement compoundStmt = (ICPPASTCompoundStatement)body; + bodyStmts = compoundStmt.getStatements(); + } else { + bodyStmts = new IASTStatement[]{body}; + } + + ICPPExecution[] bodyStmtExecutions = new ICPPExecution[bodyStmts.length]; + for(int i = 0; i < bodyStmts.length; i++) { + bodyStmtExecutions[i] = EvalUtil.getExecutionFromStatement(bodyStmts[i]); + } + return new ExecSwitch(controllerExprEval, controllerDeclExec, bodyStmtExecutions); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java index 3d9079a248a..30940348d43 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java @@ -29,7 +29,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; @@ -142,8 +143,8 @@ public class CPPASTTemplateId extends CPPASTNameBase implements ICPPASTTemplateI buf.append(arg.getRawSignature()); cleanupWhitespace= true; } else if (arg instanceof IASTExpression) { - IValue value= Value.create((IASTExpression) arg); - if (value != Value.UNKNOWN && !Value.isDependentValue(value)) { + IValue value= ValueFactory.create((IASTExpression) arg); + if (value != IntegralValue.UNKNOWN && !IntegralValue.isDependentValue(value)) { buf.append(value.getSignature()); } else { buf.append(arg.getRawSignature()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdExpression.java index 2804c76442c..cac64d46d42 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdExpression.java @@ -24,7 +24,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnaryTypeID; -public class CPPASTTypeIdExpression extends ASTNode implements ICPPASTTypeIdExpression { +public class CPPASTTypeIdExpression extends ASTNode implements ICPPASTTypeIdExpression, ICPPEvaluationOwner { private int fOperator; private IASTTypeId fTypeId; private ICPPEvaluation fEvaluation; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdInitializerExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdInitializerExpression.java index 6632bcf83ae..36a8e3a1b03 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdInitializerExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdInitializerExpression.java @@ -32,7 +32,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; * Type id initializer expression for C++, type-id { initializer } */ public class CPPASTTypeIdInitializerExpression extends ASTNode - implements IASTTypeIdInitializerExpression, ICPPASTExpression { + implements IASTTypeIdInitializerExpression, ICPPASTExpression, ICPPEvaluationOwner { private IASTTypeId fTypeId; private IASTInitializer fInitializer; private ICPPEvaluation fEvaluation; @@ -146,7 +146,7 @@ public class CPPASTTypeIdInitializerExpression extends ASTNode if (type == null || type instanceof IProblemType) return EvalFixed.INCOMPLETE; - return new EvalTypeId(type, this, ((ICPPASTInitializerClause) initializer).getEvaluation()); + return new EvalTypeId(type, this, false, ((ICPPEvaluationOwner) initializer).getEvaluation()); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java index d2d3ba34de7..3c5c78033cb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java @@ -41,7 +41,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.FunctionSetType; /** * Unary expression in c++ */ -public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpression, IASTAmbiguityParent { +public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpression, IASTAmbiguityParent, ICPPEvaluationOwner { private int fOperator; private ICPPASTExpression fOperand; private ICPPEvaluation fEvaluation; @@ -196,7 +196,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres if (fOperand == null) return EvalFixed.INCOMPLETE; - final ICPPEvaluation nestedEval = fOperand.getEvaluation(); + final ICPPEvaluation nestedEval = ((ICPPEvaluationOwner)fOperand).getEvaluation(); if (fOperator == op_bracketedPrimary) return nestedEval; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTWhileStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTWhileStatement.java index 824a39eb672..8fb6faf9704 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTWhileStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTWhileStatement.java @@ -19,11 +19,14 @@ import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSimpleDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecWhile; /** * While statement in C++. */ -public class CPPASTWhileStatement extends CPPASTAttributeOwner implements ICPPASTWhileStatement { +public class CPPASTWhileStatement extends CPPASTAttributeOwner implements ICPPASTWhileStatement, ICPPExecutionOwner { private IASTExpression condition; private IASTDeclaration condition2; private IASTStatement body; @@ -152,4 +155,14 @@ public class CPPASTWhileStatement extends CPPASTAttributeOwner implements ICPPAS scope = new CPPBlockScope(this); return scope; } + + @Override + public ICPPExecution getExecution() { + ICPPEvaluationOwner conditionExpr = (ICPPEvaluationOwner)getCondition(); + ICPPExecutionOwner conditionDecl = (ICPPExecutionOwner)getConditionDeclaration(); + ICPPEvaluation conditionExprEval = conditionExpr != null ? conditionExpr.getEvaluation() : null; + ExecSimpleDeclaration conditionDeclExec = conditionDecl != null ? (ExecSimpleDeclaration)conditionDecl.getExecution() : null; + ICPPExecution bodyExec = EvalUtil.getExecutionFromStatement(getBody()); + return new ExecWhile(conditionExprEval, conditionDeclExec, bodyExec); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPArrayType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPArrayType.java index 17c1ae5cfa5..e00629da487 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPArrayType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPArrayType.java @@ -22,13 +22,14 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.core.runtime.CoreException; public class CPPArrayType implements IArrayType, ITypeContainer, ISerializableType { private IType type; private IASTExpression sizeExpression; - private IValue value= Value.NOT_INITIALIZED; + private IValue value= IntegralValue.NOT_INITIALIZED; public CPPArrayType(IType type, IValue value) { this.value= value; @@ -78,18 +79,18 @@ public class CPPArrayType implements IArrayType, ITypeContainer, ISerializableTy @Override public IValue getSize() { - if (value != Value.NOT_INITIALIZED) + if (value != IntegralValue.NOT_INITIALIZED) return value; if (sizeExpression == null) return value= null; - return value= Value.create(sizeExpression); + return value= ValueFactory.create(sizeExpression); } @Override public boolean hasSize() { - return value == Value.NOT_INITIALIZED ? sizeExpression != null : value != null; + return value == IntegralValue.NOT_INITIALIZED ? sizeExpression != null : value != null; } @Override @@ -125,9 +126,9 @@ public class CPPArrayType implements IArrayType, ITypeContainer, ISerializableTy return; } - Long num= val.numericalValue(); + Number num= val.numberValue(); if (num != null) { - long lnum= num; + long lnum= num.longValue(); if (lnum >= 0) { buffer.putShort((short) (firstBytes | ITypeMarshalBuffer.FLAG1)); buffer.putLong(lnum); @@ -143,7 +144,7 @@ public class CPPArrayType implements IArrayType, ITypeContainer, ISerializableTy public static IType unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { IValue value= null; if ((firstBytes & ITypeMarshalBuffer.FLAG1) != 0) { - value = Value.create(buffer.getLong()); + value = IntegralValue.create(buffer.getLong()); } else if ((firstBytes & ITypeMarshalBuffer.FLAG2) != 0) { value = buffer.unmarshalValue(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java index cd943e5a0d7..504f0ce2f54 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java @@ -24,7 +24,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.core.runtime.CoreException; /** @@ -70,7 +70,8 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType { } fModifiers= qualifiers; if (expression instanceof ICPPASTInitializerClause) { - fAssociatedValue = Value.create(expression).numericalValue(); + Number num = ValueFactory.create(expression).numberValue(); + fAssociatedValue = num != null ? num.longValue() : null; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java index 053ade7c537..93af498af8d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java @@ -112,15 +112,15 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { if (!ia.hasUserDeclaredConstructor()) { // Default constructor: A(void) - boolean isConstexpr = ia.isDefaultConstructorConstexpr(); - ICPPMethod m = new CPPImplicitConstructor(this, className, EMPTY_CPPPARAMETER_ARRAY, isConstexpr); + ICPPMethod m = new CPPImplicitConstructor(this, className, EMPTY_CPPPARAMETER_ARRAY, + compTypeSpec); implicits[i++] = m; addBinding(m); } if (!ia.hasUserDeclaredCopyConstructor()) { // Copy constructor: A(const A &) - ICPPMethod m = new CPPImplicitConstructor(this, className, params, false); + ICPPMethod m = new CPPImplicitConstructor(this, className, params, compTypeSpec); implicits[i++] = m; addBinding(m); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java index 85969069f49..89d4b414b38 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java @@ -91,6 +91,11 @@ public class CPPClassSpecialization extends CPPSpecialization public ICompositeType getCompositeTypeOwner() { return null; } + + @Override + public byte getFieldPosition() { + return -1; + } } public final static class RecursionResolvingMethod extends RecursionResolvingBinding implements ICPPMethod { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java index e8ce53e481b..d06ae806038 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java @@ -80,14 +80,15 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP // Deleted default constructor: A() CPPImplicitConstructor ctor= - new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, ICPPParameter.EMPTY_CPPPARAMETER_ARRAY, false); + new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, + ICPPParameter.EMPTY_CPPPARAMETER_ARRAY, fLambdaExpression); ctor.setDeleted(true); result[0]= ctor; // Copy constructor: A(const A &) IType pType = new CPPReferenceType(SemanticUtil.constQualify(this), false); ICPPParameter[] ps = new ICPPParameter[] { new CPPParameter(pType, 0) }; - ctor = new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, ps, false); + ctor = new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, ps, fLambdaExpression); result[1]= ctor; // Deleted copy assignment operator: A& operator = (const A &) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructor.java index e114e5b33ba..3d0c28c73ca 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructor.java @@ -11,12 +11,83 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.core.dom.ast.IASTInitializer; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalConstructor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecConstructorChain; public class CPPConstructor extends CPPMethod implements ICPPConstructor { public CPPConstructor(ICPPASTFunctionDeclarator declarator) { super(declarator); } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return getConstructorChainExecution(this); + } + + private static ICPPEvaluation getMemberEvaluation(ICPPField member, ICPPASTConstructorChainInitializer chainInitializer, IASTNode point) { + final IASTInitializer initializer = chainInitializer.getInitializer(); + if(initializer instanceof ICPPEvaluationOwner) { + return ((ICPPEvaluationOwner) initializer).getEvaluation(); + } else if(initializer instanceof ICPPASTConstructorInitializer) { + ICPPConstructor constructor = (ICPPConstructor)CPPSemantics.findImplicitlyCalledConstructor(chainInitializer); + if (constructor == null) { + boolean usesBracedInitList = (initializer instanceof ICPPASTInitializerList); + return new EvalTypeId(member.getType(), point, usesBracedInitList, + EvalConstructor.extractArguments(initializer)); + } + return new EvalConstructor(member.getType(), constructor, EvalConstructor.extractArguments(initializer), point); + } + return null; + } + + static ICPPExecution computeConstructorChainExecution(IASTNode def) { + ICPPASTFunctionDefinition fnDef = getFunctionDefinition(def); + if (fnDef != null) { + final ICPPASTConstructorChainInitializer[] ccInitializers = fnDef.getMemberInitializers(); + final Map resultPairs = new HashMap<>(); + for(ICPPASTConstructorChainInitializer ccInitializer : ccInitializers) { + final IBinding member = ccInitializer.getMemberInitializerId().resolveBinding(); + if(member instanceof ICPPField) { + final ICPPField fieldMember = (ICPPField)member; + final ICPPEvaluation memberEval = getMemberEvaluation(fieldMember, ccInitializer, fnDef); + resultPairs.put(fieldMember, memberEval); + } else if(member instanceof ICPPConstructor) { + final ICPPConstructor ctorMember = (ICPPConstructor)member; + final IASTInitializer initializer = ccInitializer.getInitializer(); + if (initializer instanceof ICPPASTConstructorInitializer || + initializer instanceof ICPPASTInitializerList) { + final ICPPClassType baseClassType = (ICPPClassType)ctorMember.getOwner(); + EvalConstructor memberEval = new EvalConstructor(baseClassType, ctorMember, + EvalConstructor.extractArguments(initializer, ctorMember), fnDef); + resultPairs.put(ctorMember, memberEval); + } + } + } + return new ExecConstructorChain(resultPairs); + } + return null; + } + + static ICPPExecution getConstructorChainExecution(CPPFunction function) { + if(!function.isConstexpr()) + return null; + return computeConstructorChainExecution(function.getDefinition()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorInstance.java index 5b6c59f5337..2c588280f79 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorInstance.java @@ -11,6 +11,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; @@ -27,4 +28,9 @@ public class CPPConstructorInstance extends CPPMethodInstance implements ICPPCon ICPPTemplateArgument[] args, ICPPFunctionType type, IType[] exceptionSpec) { super(orig, owner, tpmap, args, type, exceptionSpec); } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return CPPConstructorSpecialization.getConstructorChainExecution(this, point); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorSpecialization.java index 9a8837623e0..0cd51970193 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorSpecialization.java @@ -11,11 +11,14 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; /** * Specialization of a constructor for a class-template or class-template specialization. @@ -26,4 +29,22 @@ public class CPPConstructorSpecialization extends CPPMethodSpecialization implem ICPPTemplateParameterMap argMap, ICPPFunctionType type, IType[] exceptionSpecs) { super(orig, owner, argMap, type, exceptionSpecs); } + + static ICPPExecution + getConstructorChainExecution(T functionSpec, IASTNode point) { + if (!functionSpec.isConstexpr()) { + return null; + } + + IASTNode def = functionSpec.getDefinition(); + if(def != null) { + return CPPConstructor.computeConstructorChainExecution(def); + } + return CPPTemplates.instantiateConstructorChain(functionSpec, point); + } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return getConstructorChainExecution(this, point); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplate.java index 95f774ec692..14a6f766615 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplate.java @@ -11,6 +11,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; public class CPPConstructorTemplate extends CPPMethodTemplate implements ICPPConstructor { @@ -18,4 +19,12 @@ public class CPPConstructorTemplate extends CPPMethodTemplate implements ICPPCon public CPPConstructorTemplate(IASTName name) { super(name); } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + if (!isConstexpr()) { + return null; + } + return CPPConstructor.computeConstructorChainExecution(getDefinition()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplateSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplateSpecialization.java index 9d2cf3df74d..b52d1b41d87 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplateSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPConstructorTemplateSpecialization.java @@ -11,6 +11,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; @@ -27,4 +28,9 @@ public class CPPConstructorTemplateSpecialization extends CPPMethodTemplateSpeci ICPPClassSpecialization owner, ICPPTemplateParameterMap tpmap, ICPPFunctionType type, IType[] exceptionSpecs) { super(original, owner, tpmap, type, exceptionSpecs); } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return CPPConstructorSpecialization.getConstructorChainExecution(this, point); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredConstructor.java similarity index 82% rename from core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownConstructor.java rename to core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredConstructor.java index 3c72b406718..c11f006413a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredConstructor.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; @@ -20,13 +21,13 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; * Represents a reference to a constructor (instance), which cannot be resolved because * it depends on a template parameter. A compiler would resolve it during instantiation. */ -public class CPPUnknownConstructor extends CPPDeferredFunction implements ICPPConstructor { +public class CPPDeferredConstructor extends CPPDeferredFunction implements ICPPConstructor { - public CPPUnknownConstructor(ICPPClassType owner) { + public CPPDeferredConstructor(ICPPClassType owner) { super(owner, owner.getNameCharArray(), null); } - public CPPUnknownConstructor(ICPPClassType owner, ICPPFunction[] candidates) { + public CPPDeferredConstructor(ICPPClassType owner, ICPPFunction[] candidates) { super(owner, owner.getNameCharArray(), candidates); } @@ -74,4 +75,9 @@ public class CPPUnknownConstructor extends CPPDeferredFunction implements ICPPCo public boolean isFinal() { return false; } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java index d88e0c1df65..7d01ab314bf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java @@ -16,18 +16,23 @@ import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeferredFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; +import org.eclipse.core.runtime.CoreException; /** * Represents a reference to a (member) function (instance), which cannot be resolved because * an argument depends on a template parameter. A compiler would resolve it during instantiation. */ -public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPDeferredFunction, ICPPComputableFunction { +public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPDeferredFunction, + ICPPComputableFunction, ISerializableType { private static final ICPPFunctionType FUNCTION_TYPE= new CPPFunctionType(ProblemType.UNKNOWN_FOR_EXPRESSION, IType.EMPTY_TYPE_ARRAY); @@ -41,7 +46,7 @@ public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPDeferr */ public static ICPPFunction createForCandidates(ICPPFunction... candidates) { if (candidates[0] instanceof ICPPConstructor) - return new CPPUnknownConstructor(((ICPPConstructor) candidates[0]).getClassOwner(), candidates); + return new CPPDeferredConstructor(((ICPPConstructor) candidates[0]).getClassOwner(), candidates); final IBinding owner = candidates[0].getOwner(); return new CPPDeferredFunction(owner, candidates[0].getNameCharArray(), candidates); @@ -166,4 +171,46 @@ public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPDeferr public ICPPEvaluation getReturnExpression(IASTNode point) { return null; } + + @Override + public ICPPExecution getFunctionBodyExecution(IASTNode point) { + return null; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer) throws CoreException { + short firstBytes = ITypeMarshalBuffer.DEFERRED_FUNCTION; + if (this instanceof CPPDeferredConstructor) { + firstBytes |= ITypeMarshalBuffer.FLAG1; + } + + buffer.putShort(firstBytes); + buffer.putCharArray(getNameCharArray()); + buffer.marshalBinding(getOwner()); + if (getCandidates() != null) { + buffer.putInt(getCandidates().length); + for (ICPPFunction candidate : getCandidates()) { + buffer.marshalBinding(candidate); + } + } else { + buffer.putInt(0); + } + } + + public static IBinding unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + char[] name = buffer.getCharArray(); + IBinding owner = buffer.unmarshalBinding(); + int length = buffer.getInt(); + ICPPFunction[] candidates = null; + if (length > 0) { + candidates = new ICPPFunction[length]; + for (int i = 0; i < candidates.length; ++i) { + candidates[i] = (ICPPFunction) buffer.unmarshalBinding(); + } + } + if ((firstBytes & ITypeMarshalBuffer.FLAG1) != 0 && (owner instanceof ICPPClassType)) { + return new CPPDeferredConstructor((ICPPClassType) owner, candidates); + } + return new CPPDeferredFunction(owner, name, candidates); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerationSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerationSpecialization.java index 3836ef8e9f7..484ee955d2f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerationSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerationSpecialization.java @@ -26,7 +26,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ASTEnumerator; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; @@ -67,7 +67,7 @@ public class CPPEnumerationSpecialization extends CPPSpecialization implements I IEnumerator enumerator = enumerators[i]; InstantiationContext context = new InstantiationContext(tpMap, this, point); IValue specializedValue = - CPPTemplates.instantiateValue(enumerator.getValue(), context, Value.MAX_RECURSION_DEPTH); + CPPTemplates.instantiateValue(enumerator.getValue(), context, IntegralValue.MAX_RECURSION_DEPTH); IType internalType = null; if (fFixedType == null && enumerator instanceof ICPPInternalEnumerator) { internalType = ((ICPPInternalEnumerator) enumerator).getInternalType(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerator.java index e782ee83bbf..9c076d8c862 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerator.java @@ -27,7 +27,7 @@ import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.ASTEnumerator; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalEnumerationSpecifier; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.core.runtime.PlatformObject; @@ -156,7 +156,7 @@ public class CPPEnumerator extends PlatformObject if (parent instanceof ASTEnumerator) return ((ASTEnumerator) parent).getIntegralValue(); - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPField.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPField.java index 6da4dd8665e..8d4115237e2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPField.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPField.java @@ -15,6 +15,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.ICompositeType; +import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; @@ -47,6 +48,11 @@ public class CPPField extends CPPVariable implements ICPPField { public ICompositeType getCompositeTypeOwner() { return getClassOwner(); } + + @Override + public byte getFieldPosition() { + return -1; + } } public CPPField(IASTName name) { @@ -91,4 +97,19 @@ public class CPPField extends CPPVariable implements ICPPField { public ICompositeType getCompositeTypeOwner() { return getClassOwner(); } + + @Override + public byte getFieldPosition() { + return getFieldPosition(getName(), getClassOwner()); + } + + public static byte getFieldPosition(String fieldName, ICPPClassType classOwner) { + IField[] fields = ClassTypeHelper.getDeclaredFields(classOwner, null); + for (byte fieldPos = 0; fieldPos < fields.length; fieldPos++) { + if (fields[fieldPos].getName().equals(fieldName)) { + return fieldPos; + } + } + return -1; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldInstance.java index 980b9136835..48ba97475dc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldInstance.java @@ -52,4 +52,9 @@ public class CPPFieldInstance extends CPPVariableInstance implements ICPPField { return null; } } + + @Override + public byte getFieldPosition() { + return ((ICPPFieldTemplate)getSpecializedBinding()).getFieldPosition(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java index e268e6e3332..4ef92581eca 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java @@ -22,15 +22,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; /** * Binding for a specialization of a field. */ -public class CPPFieldSpecialization extends CPPSpecialization implements ICPPField { - private final IType type; - private final IValue value; - +public class CPPFieldSpecialization extends CPPVariableSpecialization implements ICPPField { public CPPFieldSpecialization(IBinding orig, ICPPClassType owner, ICPPTemplateParameterMap tpmap, IType type, IValue value) { - super(orig, owner, tpmap); - this.type= type; - this.value= value; + super(orig, owner, tpmap, type, value); } private ICPPField getField() { @@ -47,48 +42,13 @@ public class CPPFieldSpecialization extends CPPSpecialization implements ICPPFie return (ICPPClassType) getOwner(); } - @Override - public IType getType() { - return type; - } - - @Override - public boolean isStatic() { - return getField().isStatic(); - } - - @Override - public boolean isExtern() { - return getField().isExtern(); - } - - @Override - public boolean isAuto() { - return getField().isAuto(); - } - - @Override - public boolean isRegister() { - return getField().isRegister(); - } - - @Override - public boolean isMutable() { - return getField().isMutable(); - } - - @Override - public boolean isExternC() { - return false; - } - @Override public ICompositeType getCompositeTypeOwner() { return getClassOwner(); } @Override - public IValue getInitialValue() { - return value; + public byte getFieldPosition() { + return getField().getFieldPosition(); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldTemplate.java index cce89b207c0..3b45756432c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldTemplate.java @@ -11,11 +11,14 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.ICompositeType; +import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFieldTemplate; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope; public class CPPFieldTemplate extends CPPVariableTemplate implements ICPPFieldTemplate { @@ -35,7 +38,22 @@ public class CPPFieldTemplate extends CPPVariableTemplate implements ICPPFieldTe @Override public ICPPClassType getClassOwner() { - ICPPClassScope scope = (ICPPClassScope) getScope(); - return scope.getClassType(); + IScope scope= getScope(); + if (scope instanceof ICPPTemplateScope) { + try { + scope= scope.getParent(); + } catch (DOMException e) { + return null; + } + } + if (scope instanceof ICPPClassScope) { + return ((ICPPClassScope) scope).getClassType(); + } + return null; + } + + @Override + public byte getFieldPosition() { + return CPPField.getFieldPosition(getName(), getClassOwner()); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldTemplatePartialSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldTemplatePartialSpecialization.java index 7cecce8c099..f675b34bbde 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldTemplatePartialSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldTemplatePartialSpecialization.java @@ -43,4 +43,9 @@ public class CPPFieldTemplatePartialSpecialization extends CPPVariableTemplatePa ICPPClassScope scope = (ICPPClassScope) getScope(); return scope.getClassType(); } + + @Override + public byte getFieldPosition() { + return ((ICPPFieldTemplate) getPrimaryTemplate()).getFieldPosition(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java index b7d89a630f2..06c69250083 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java @@ -41,7 +41,6 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; @@ -484,7 +483,7 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt return false; } - static ICPPASTFunctionDefinition getFunctionDefinition(IASTNode def) { + public static ICPPASTFunctionDefinition getFunctionDefinition(IASTNode def) { while (def != null && !(def instanceof IASTDeclaration)) { def= def.getParent(); } @@ -704,8 +703,8 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt return EvalFixed.INCOMPLETE; // constexpr constructors are not supported yet. IASTInitializerClause returnExpression = returnStatement.getReturnArgument(); - if (returnExpression instanceof ICPPASTInitializerClause) - return ((ICPPASTInitializerClause) returnExpression).getEvaluation(); + if (returnExpression instanceof ICPPEvaluationOwner) + return ((ICPPEvaluationOwner) returnExpression).getEvaluation(); return EvalFixed.INCOMPLETE; } @@ -716,4 +715,41 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt } return null; } + + public static ICPPExecution getFunctionBodyExecution(ICPPFunction function, IASTNode point) { + if (function instanceof ICPPComputableFunction) { + return ((ICPPComputableFunction) function).getFunctionBodyExecution(point); + } + return null; + } + + @Override + public ICPPExecution getFunctionBodyExecution(IASTNode point) { + if(!isConstexpr()) + return null; + if (getDefinition() == null) { + // Trigger a search for the function definition. + if (declarations != null && declarations[0] != null) { + IASTTranslationUnit tu = declarations[0].getTranslationUnit(); + if (tu != null) { + tu.getDefinitionsInAST(this); + } + } + } + return computeFunctionBodyExecution(getDefinition()); + } + + public static ICPPExecution computeFunctionBodyExecution(IASTNode def) { + ICPPASTFunctionDefinition fnDef = getFunctionDefinition(def); + if (fnDef != null) { + // Make sure ambiguity resolution has been performed on the function body, even + // if it's a class method and we're still processing the class declaration. + ((ASTNode) fnDef).resolvePendingAmbiguities(); + if(fnDef.getBody() instanceof CPPASTCompoundStatement) { + CPPASTCompoundStatement body = (CPPASTCompoundStatement)fnDef.getBody(); + return body.getExecution(); + } + } + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java index a586fe1d0c6..2d7f2376518 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java @@ -36,7 +36,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; @@ -338,10 +338,23 @@ public class CPPFunctionSpecialization extends CPPSpecialization implements ICPP ICPPClassSpecialization within = CPPTemplates.getSpecializationContext(getOwner()); InstantiationContext context = new InstantiationContext(getTemplateParameterMap(), within, point); - eval = eval.instantiate(context, Value.MAX_RECURSION_DEPTH); + eval = eval.instantiate(context, IntegralValue.MAX_RECURSION_DEPTH); } return eval; } return null; } + + @Override + public ICPPExecution getFunctionBodyExecution(IASTNode point) { + if (!isConstexpr()) { + return null; + } + + IASTNode def = getDefinition(); + if(def != null) { + return CPPFunction.computeFunctionBodyExecution(def); + } + return CPPTemplates.instantiateFunctionBody(this, point); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java index ac87d0ce010..3b05db3a478 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java @@ -446,4 +446,12 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition return EvalFixed.INCOMPLETE; return CPPFunction.getReturnExpression(functionDefinition); } + + @Override + public ICPPExecution getFunctionBodyExecution(IASTNode point) { + if (!isConstexpr()) { + return null; + } + return CPPFunction.computeFunctionBodyExecution(getDefinition()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitConstructor.java index 7276855a28a..9cfdd219fb9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitConstructor.java @@ -14,23 +14,50 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import static org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType.UNSPECIFIED_TYPE; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeTraits; /** * Binding for implicit constructors (default and copy constructor). */ public class CPPImplicitConstructor extends CPPImplicitMethod implements ICPPConstructor { - public CPPImplicitConstructor(ICPPClassScope scope, char[] name, ICPPParameter[] params, boolean isConstexpr) { - super(scope, name, createFunctionType(params), params, isConstexpr); + IASTNode fPoint; // point of instantiation, if applicable + + public CPPImplicitConstructor(ICPPClassScope scope, char[] name, ICPPParameter[] params, IASTNode point) { + // Note: the value passed for the 'isConstexpr' parameter of the CPPImplicitMethod constructor + // is irrelevant, as CPPImplicitConstructor overrides isConstexpr(). + super(scope, name, createFunctionType(params), params, false); + fPoint = point; } private static ICPPFunctionType createFunctionType(IParameter[] params) { return CPPVisitor.createImplicitFunctionType(UNSPECIFIED_TYPE, params, false, false); } + + + /* + * From $12.1 / 5: + * The implicitly-defined default constructor performs the set of initializations of the class that would + * be performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and + * an empty compound-statement. […] If that user-written default constructor would satisfy the requirements + * of a constexpr constructor (7.1.5), the implicitly-defined default constructor is constexpr. + * + * Therefore, an implicitly-defined constructor should be considered constexpr if the class type is a literal type. + */ + @Override + public boolean isConstexpr() { + return TypeTraits.isLiteralClass(getClassOwner(), fPoint); + } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return CPPConstructor.getConstructorChainExecution(this); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeArgument.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeArgument.java index f45504f91c9..ff641916a5f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeArgument.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeArgument.java @@ -18,7 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalParameterPack; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; @@ -37,7 +37,7 @@ public class CPPTemplateNonTypeArgument implements ICPPTemplateArgument { fEvaluation= evaluation; } else { IValue value = evaluation.getValue(point); - if (value == Value.ERROR) { + if (value == IntegralValue.ERROR) { fEvaluation = EvalFixed.INCOMPLETE; } else { fEvaluation= new EvalFixed(evaluation.getType(point), @@ -100,7 +100,7 @@ public class CPPTemplateNonTypeArgument implements ICPPTemplateArgument { if (fEvaluation instanceof EvalParameterPack) { evaluation = ((EvalParameterPack) fEvaluation).getExpansionPattern(); } else { - evaluation = new EvalTypeId(t, fEvaluation.getTemplateDefinition(), fEvaluation); + evaluation = new EvalTypeId(t, fEvaluation.getTemplateDefinition(), false, false, fEvaluation); } return new CPPTemplateNonTypeArgument(evaluation, null); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeParameter.java index 89959e7f7a9..49bec05f420 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeParameter.java @@ -26,7 +26,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; /** @@ -81,7 +82,7 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter ICPPASTInitializerList list= (ICPPASTInitializerList) dc; switch (list.getSize()) { case 0: - return new CPPTemplateNonTypeArgument(Value.create(0), getType()); + return new CPPTemplateNonTypeArgument(IntegralValue.create(0), getType()); case 1: dc= list.getClauses()[0]; if (dc instanceof IASTExpression) { @@ -93,7 +94,7 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter if (d == null) return null; - IValue val= Value.create(d); + IValue val= ValueFactory.create(d); IType t= getType(); return new CPPTemplateNonTypeArgument(val, t); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTypedefSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTypedefSpecialization.java index 1ae141fc3b2..4c3076c4c05 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTypedefSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTypedefSpecialization.java @@ -15,7 +15,6 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; @@ -28,7 +27,7 @@ public class CPPTypedefSpecialization extends CPPSpecialization implements IType private IType fType; - public CPPTypedefSpecialization(IBinding specialized, ICPPClassType owner, + public CPPTypedefSpecialization(IBinding specialized, IBinding owner, ICPPTemplateParameterMap tpmap, IType type) { super(specialized, owner, tpmap); fType= type; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownField.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownField.java index aa8db202bcb..feee867692d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownField.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownField.java @@ -85,4 +85,9 @@ public class CPPUnknownField extends CPPUnknownMember implements ICPPField { public IValue getInitialValue() { return null; } + + @Override + public byte getFieldPosition() { + return -1; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUsingDeclarationSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUsingDeclarationSpecialization.java index b12b10327e0..f97c252b944 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUsingDeclarationSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUsingDeclarationSpecialization.java @@ -11,7 +11,6 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.IBinding; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; @@ -21,7 +20,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; public class CPPUsingDeclarationSpecialization extends CPPSpecialization implements ICPPUsingDeclaration { private final IBinding[] fDelegates; - public CPPUsingDeclarationSpecialization(ICPPUsingDeclaration specialized, ICPPClassSpecialization owner, + public CPPUsingDeclarationSpecialization(ICPPUsingDeclaration specialized, IBinding owner, ICPPTemplateParameterMap tpmap, IBinding[] delegates) { super(specialized, owner, tpmap); fDelegates= delegates; 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 10f0a8bf5d6..02c73b50f1f 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 @@ -13,12 +13,19 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; + import java.util.HashSet; import java.util.Set; import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; +import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IArrayType; @@ -26,13 +33,23 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalConstructor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.core.runtime.PlatformObject; public class CPPVariable extends PlatformObject implements ICPPInternalVariable { @@ -51,7 +68,7 @@ public class CPPVariable extends PlatformObject implements ICPPInternalVariable return new HashSet<>(); } }; - + public CPPVariable(IASTName name) { boolean isDef = name != null && name.isDefinition(); if (name instanceof ICPPASTQualifiedName) { @@ -216,17 +233,86 @@ public class CPPVariable extends PlatformObject implements ICPPInternalVariable public IValue getInitialValue() { Set recursionProtectionSet = fInitialValueInProgress.get(); if (!recursionProtectionSet.add(this)) { - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } try { - return VariableHelpers.getInitialValue(fDefinition, fDeclarations, getType()); + IValue initialValue = null; + final IType nestedType = SemanticUtil.getNestedType(getType(), TDEF | REF | CVTYPE); + if(nestedType instanceof ICPPClassType || (initialValue = VariableHelpers.getInitialValue(fDefinition, fDeclarations, getType())) == IntegralValue.UNKNOWN) { + ICPPEvaluation initEval = getInitializerEvaluation(); + if(initEval == null) { + return null; + } + return IntegralValue.create(initEval); + } + return initialValue; } finally { recursionProtectionSet.remove(this); } } + + private IASTDeclarator findDeclarator() { + IASTDeclarator declarator = null; + if (fDefinition != null) { + declarator = VariableHelpers.findDeclarator(fDefinition); + if(declarator != null) { + return declarator; + } + } + if (fDeclarations != null) { + for (IASTName decl : fDeclarations) { + if (decl == null) + break; + declarator = VariableHelpers.findDeclarator(decl); + if(declarator != null) { + return declarator; + } + } + } + return null; + } @Override public String toString() { return getName(); } + + /** + * Return an evaluation representing the variable's initialization. + * + * If the variable has no initializer, null is returned. + */ + public ICPPEvaluation getInitializerEvaluation() { + ICPPASTDeclarator declarator = (ICPPASTDeclarator)findDeclarator(); + if(declarator != null) { + IASTInitializer initializer = declarator.getInitializer(); + ICPPConstructor constructor = getImplicitlyCalledCtor(declarator); + if(constructor != null) { + ICPPEvaluation[] arguments = EvalConstructor.extractArguments(initializer, constructor); + return new EvalConstructor(getType(), constructor, arguments, declarator); + } else if(initializer instanceof IASTEqualsInitializer) { + IASTEqualsInitializer equalsInitializer = (IASTEqualsInitializer)initializer; + ICPPEvaluationOwner evalOwner = (ICPPEvaluationOwner)equalsInitializer.getInitializerClause(); + return evalOwner.getEvaluation(); + } else if(initializer instanceof ICPPASTInitializerList) { + ICPPEvaluationOwner evalOwner = (ICPPEvaluationOwner)initializer; + return evalOwner.getEvaluation(); + } else if(initializer instanceof ICPPASTConstructorInitializer) { + ICPPASTConstructorInitializer ctorInitializer = (ICPPASTConstructorInitializer)initializer; + ICPPEvaluationOwner evalOwner = (ICPPEvaluationOwner)ctorInitializer.getArguments()[0]; + return evalOwner.getEvaluation(); + } else if(initializer == null) { + return null; + } + } + return EvalFixed.INCOMPLETE; + } + + private static ICPPConstructor getImplicitlyCalledCtor(ICPPASTDeclarator declarator) { + IBinding ctor = CPPSemantics.findImplicitlyCalledConstructor(declarator); + if(ctor != null && !EvalUtil.isCompilerGeneratedCtor(ctor)) { + return (ICPPConstructor)ctor; + } + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariableSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariableSpecialization.java new file mode 100644 index 00000000000..3b7cb86b4db --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariableSpecialization.java @@ -0,0 +1,70 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; + +public class CPPVariableSpecialization extends CPPSpecialization implements ICPPVariable { + private final IType type; + private final IValue value; + + public CPPVariableSpecialization(IBinding orig, IBinding owner, ICPPTemplateParameterMap tpmap, IType type, IValue value) { + super(orig, owner, tpmap); + this.type = type; + this.value = value; + } + + private ICPPVariable getVariable() { + return (ICPPVariable)getSpecializedBinding(); + } + + @Override + public IType getType() { + return type; + } + + @Override + public IValue getInitialValue() { + return value; + } + + @Override + public boolean isStatic() { + return getVariable().isStatic(); + } + + @Override + public boolean isExtern() { + return getVariable().isExtern(); + } + + @Override + public boolean isAuto() { + return getVariable().isAuto(); + } + + @Override + public boolean isRegister() { + return getVariable().isRegister(); + } + + @Override + public boolean isMutable() { + return getVariable().isMutable(); + } + + @Override + public boolean isExternC() { + return false; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPComputableFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPComputableFunction.java index f5b8452caff..f747c637fb5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPComputableFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPComputableFunction.java @@ -13,7 +13,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.IASTNode; /** - * Represents a function the return value of which may potentially be calculated at parsing time. + * Represents a function whose executing may be simulated at parsing time. */ public interface ICPPComputableFunction { /** @@ -22,4 +22,11 @@ public interface ICPPComputableFunction { * @param point the point of instantiation for name lookups */ public ICPPEvaluation getReturnExpression(IASTNode point); + + /** + * For a constexpr function returns the ICPPExecution for its body. Otherwise returns + * {@code null}. + * @param point the point of instantiation for name lookups + */ + public ICPPExecution getFunctionBodyExecution(IASTNode point); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java index a0e3ac3e9be..3af95c0665b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java @@ -19,7 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPFunctionParameterMap; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ActivationRecord; /** * Assists in evaluating expressions. @@ -88,7 +88,7 @@ public interface ICPPEvaluation extends ISerializableEvaluation { /** * Keeps track of state during a constexpr evaluation. */ - final class ConstexprEvaluationContext { + public final class ConstexprEvaluationContext { /** * The maximum number of steps allowed in a single constexpr evaluation. * This is used to prevent a buggy constexpr function from causing the @@ -136,12 +136,11 @@ public interface ICPPEvaluation extends ISerializableEvaluation { /** * Computes the evaluation produced by substituting function parameters by their values. * - * @param parameterMap maps function parameters to their values + * @param record maps function parameters and local variables to their values * @param context the context for the current constexpr evaluation * @return the computed evaluation */ - ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context); + ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context); /** * Searches the evaluation for a usage of a template parameter which is a parameter pack, diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluationOwner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluationOwner.java new file mode 100644 index 00000000000..4b503e767be --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluationOwner.java @@ -0,0 +1,16 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +public interface ICPPEvaluationOwner { + /** + * Returns the evaluation object for this expression. + */ + ICPPEvaluation getEvaluation(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPExecution.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPExecution.java new file mode 100644 index 00000000000..b326c352d4d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPExecution.java @@ -0,0 +1,35 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ActivationRecord; + +/** + * Assists in executing statements for constexpr evaluation + */ +public interface ICPPExecution extends ISerializableExecution { + /** + * Instantiates the execution with the provided template parameter map and pack offset. + * The context is used to replace templates with their specialization, where appropriate. + * + * @return a fully or partially instantiated execution, or the original execution + */ + ICPPExecution instantiate(InstantiationContext context, int maxDepth); + + /** + * Computes the execution produced by substituting function parameters by their values. + * + * @param record maps function parameters and local variables to their values + * @param context the context for the current constexpr evaluation + * @return the computed execution + */ + ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPExecutionOwner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPExecutionOwner.java new file mode 100644 index 00000000000..85b5b1b8d08 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPExecutionOwner.java @@ -0,0 +1,16 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +public interface ICPPExecutionOwner { + /** + * Returns the execution object for this statement, declaration or declarator. + */ + ICPPExecution getExecution(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java index 16b0c4d54cc..478351fc77e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java @@ -10,10 +10,14 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import java.util.HashMap; +import java.util.Map; + import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumerationSpecialization; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; @@ -25,35 +29,41 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTypeSpecialization; public final class InstantiationContext { private CPPTemplateParameterMap parameterMap; private int packOffset; - private final ICPPTypeSpecialization contextTypeSpecialization; + private final ICPPSpecialization contextSpecialization; private final IASTNode point; private boolean expandPack; private boolean packExpanded; + + // During the instantiation of a function body, stores mapping from local variables + // (including function parameters) to their instantiated versions. + // TODO(nathanridge): Get rid of this, replacing it with something analogous to + // ICPPClassSpecialization.specializeMember() but for function scopes. + private Map fInstantiatedLocals = null; /** * @param parameterMap mapping of template parameters to arguments, may be {@code null}. * @param packOffset parameter pack offset, or -1 if expansion of a parameter pack is not desired pack. - * @param contextTypeSpecialization the type specialization if instantiation happens inside a specialized - * type, otherwise {@code null}. + * @param contextSpecialization the specialization if instantiation happens inside a specialized + * type or function, otherwise {@code null}. * @param point the point of instantiation */ public InstantiationContext(ICPPTemplateParameterMap parameterMap, int packOffset, - ICPPTypeSpecialization contextTypeSpecialization, IASTNode point) { + ICPPSpecialization contextSpecialization, IASTNode point) { this.parameterMap = (CPPTemplateParameterMap) parameterMap; this.packOffset = packOffset; - this.contextTypeSpecialization = contextTypeSpecialization; + this.contextSpecialization = contextSpecialization; this.point = point; } /** * @param parameterMap mapping of template parameters to arguments, may be {@code null}. - * @param contextTypeSpecialization the type specialization if instantiation happens inside a specialized - * type, otherwise {@code null}. + * @param contextSpecialization the specialization if instantiation happens inside a specialized + * type or function, otherwise {@code null}. * @param point the point of instantiation */ public InstantiationContext(ICPPTemplateParameterMap parameterMap, - ICPPTypeSpecialization contextTypeSpecialization, IASTNode point) { - this(parameterMap, -1, contextTypeSpecialization, point); + ICPPSpecialization contextSpecialization, IASTNode point) { + this(parameterMap, -1, contextSpecialization, point); } /** @@ -112,12 +122,20 @@ public final class InstantiationContext { } } + /** + * Returns the specialization if instantiation happens inside a specialized type or function, otherwise + * {@code null} + */ + public final ICPPSpecialization getContextSpecialization() { + return contextSpecialization; + } + /** * Returns the type specialization if instantiation happens inside a specialized type, otherwise * {@code null}. */ - public ICPPTypeSpecialization getContextTypeSpecialization() { - return contextTypeSpecialization; + public final ICPPTypeSpecialization getContextTypeSpecialization() { + return contextSpecialization instanceof ICPPTypeSpecialization ? (ICPPTypeSpecialization)contextSpecialization : null; } /** @@ -125,7 +143,7 @@ public final class InstantiationContext { * {@code null}. */ public ICPPClassSpecialization getContextClassSpecialization() { - return getContextClassSpecialization(contextTypeSpecialization); + return getContextClassSpecialization(contextSpecialization); } /** @@ -203,7 +221,7 @@ public final class InstantiationContext { } /** - * Returns the class specialization that the given binding is or is owned by, otherwise {@code null}. + * Returns the class specialization that the given binding is or is owned by, otherwise {@code null}. */ public static ICPPClassSpecialization getContextClassSpecialization(IBinding owner) { if (owner instanceof ICPPEnumerationSpecialization) @@ -212,4 +230,16 @@ public final class InstantiationContext { return (ICPPClassSpecialization) owner; return null; } + + public void putInstantiatedLocal(IBinding local, IBinding instantiatedLocal) { + if (fInstantiatedLocals == null) { + fInstantiatedLocals = new HashMap<>(); + } + fInstantiatedLocals.put(local, instantiatedLocal); + } + + public IBinding getInstantiatedLocal(IBinding local) { + return fInstantiatedLocals == null ? null : fInstantiatedLocals.get(local); + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/VariableHelpers.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/VariableHelpers.java index 2c372d9d372..88eb8383020 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/VariableHelpers.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/VariableHelpers.java @@ -156,7 +156,7 @@ public class VariableHelpers { return null; } - private static IASTDeclarator findDeclarator(IASTName name) { + public static IASTDeclarator findDeclarator(IASTName name) { IASTNode node = name.getParent(); if (node instanceof ICPPASTQualifiedName) node = node.getParent(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ActivationRecord.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ActivationRecord.java new file mode 100644 index 00000000000..6d22abaeb1b --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ActivationRecord.java @@ -0,0 +1,100 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; + +/** + * ActivationRecord keeps track of the values of parameters and local variables + * during the evaluation of a function call. + * */ +public class ActivationRecord { + private final Map vars = new HashMap<>(); + private final ICPPParameter[] params; + private final ICPPEvaluation[] args; + private final ICPPEvaluation implicitThis; + + public ActivationRecord(ICPPParameter[] params, ICPPEvaluation implicitThis) { + this.params = params; + this.args = new ICPPEvaluation[params.length]; + this.implicitThis = implicitThis; + } + + public ActivationRecord() { + this(new ICPPParameter[] {}, null); + } + + public void update(IBinding binding, ICPPEvaluation value) { + int paramPos = getParameterPosition(binding); + if (paramPos == -1) { + vars.put(binding, value); + } else { + args[paramPos] = value; + } + } + + public ICPPEvaluation getVariable(IBinding binding) { + int paramPos = getParameterPosition(binding); + if (paramPos == -1) { + return vars.get(binding); + } else { + return args[paramPos]; + } + } + + private int getParameterPosition(IBinding binding) { + if(binding instanceof ICPPParameter) { + for (int i = 0; i < params.length; i++) { + ICPPParameter param = params[i]; + if (param.getName().equals(binding.getName())) { + return i; + } + } + } + return -1; + } + + public ICPPEvaluation getImplicitThis() { + return implicitThis; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Local variables: [\n"); //$NON-NLS-1$ + int i = 0; + for (Entry entry : vars.entrySet()) { + builder.append("\t\t"); //$NON-NLS-1$ + builder.append(entry.getKey().toString()); + builder.append("="); //$NON-NLS-1$ + builder.append(entry.getValue().toString()); + if (i < vars.entrySet().size() - 1) { + builder.append(", "); //$NON-NLS-1$ + } + i++; + builder.append("\n"); //$NON-NLS-1$ + } + builder.append("]\n"); //$NON-NLS-1$ + + builder.append("Implicit this: "); //$NON-NLS-1$ + if (implicitThis != null) { + builder.append(implicitThis.toString()); + } else { + builder.append(""); //$NON-NLS-1$ + } + builder.append("\n"); //$NON-NLS-1$ + return builder.toString(); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java index 27395450175..e49ac79ad89 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java @@ -21,6 +21,7 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; @@ -126,7 +127,11 @@ public abstract class CPPEvaluation implements ICPPEvaluation { } ICPPEvaluation innerEval = value.getEvaluation(); if (innerEval == null) { - return value.numericalValue() != null; + if(value instanceof IntegralValue) { + return value.numberValue() != null; + } else { + return true; + } } return innerEval.isConstantExpression(point); } @@ -163,7 +168,7 @@ public abstract class CPPEvaluation implements ICPPEvaluation { return EvalFixed.INCOMPLETE; } ICPPEvaluation eval = new EvalBinding(conversion, null, (IBinding) null); - argument = new EvalFunctionCall(new ICPPEvaluation[] {eval, argument}, (IBinding) null); + argument = new EvalFunctionCall(new ICPPEvaluation[] {eval, argument}, null, (IBinding) null); } return argument; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 443dacb9716..8436fca1b7f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -118,7 +118,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; @@ -196,8 +195,8 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope; import org.eclipse.cdt.internal.core.dom.parser.IRecursionResolvingBinding; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName; @@ -216,7 +215,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownConstructor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredConstructor; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownField; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMemberClass; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMethod; @@ -228,6 +227,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluationOwner; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalNamespaceScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; @@ -460,7 +460,7 @@ public class CPPSemantics { } } if (cls instanceof ICPPUnknownBinding) { - binding= new CPPUnknownConstructor(cls); + binding= new CPPDeferredConstructor(cls); } else { // Do not interpret template arguments to a template class as being // explicit template arguments to its templated constructor. @@ -1251,7 +1251,7 @@ public class CPPSemantics { if (expression instanceof ICPPASTLiteralExpression) { final ICPPASTLiteralExpression litExpr = (ICPPASTLiteralExpression) expression; if (litExpr.getKind() == IASTLiteralExpression.lk_this) { - final IType thisType = SemanticUtil.getNestedType(litExpr.getEvaluation().getType(litExpr), TDEF | ALLCVQ | PTR | ARRAY | MPTR | REF); + final IType thisType = SemanticUtil.getNestedType(((ICPPEvaluationOwner)litExpr).getEvaluation().getType(litExpr), TDEF | ALLCVQ | PTR | ARRAY | MPTR | REF); if (thisType instanceof ICPPUnknownBinding || thisType instanceof ICPPTemplateDefinition) { result[0]= true; return PROCESS_ABORT; @@ -2904,7 +2904,7 @@ public class CPPSemantics { return result; } - static IType getImplicitParameterType(ICPPMethod m) throws DOMException { + static IType getImplicitParameterType(ICPPMethod m) { IType implicitType; ICPPClassType owner= m.getClassOwner(); if (owner instanceof ICPPClassTemplate) { @@ -2914,7 +2914,7 @@ public class CPPSemantics { implicitType= SemanticUtil.addQualifiers(owner, ft.isConst(), ft.isVolatile(), false); return new CPPReferenceType(implicitType, ft.isRValueReference()); } - + private static IBinding resolveUserDefinedConversion(LookupData data, ICPPFunction[] fns) { ICPPASTConversionName astName= (ICPPASTConversionName) data.getLookupName(); IType t= CPPVisitor.createType(astName.getTypeId()); @@ -3096,7 +3096,7 @@ public class CPPSemantics { // If we're in a dependent context, we don't have enough information // to resolve the function set. - if (((ICPPASTExpression) parent).getEvaluation().isTypeDependent()) { + if (((ICPPEvaluationOwner) parent).getEvaluation().isTypeDependent()) { return CPPDeferredFunction.createForCandidates(functionSet.getBindings()); } } @@ -3108,7 +3108,26 @@ public class CPPSemantics { return function; } - /** + private static boolean isViableUserDefinedLiteralOperator(IBinding binding, int kind) { + if(binding == null || binding instanceof ProblemBinding) { + return false; + } + if(binding instanceof ICPPFunction) { + ICPPFunction func = (ICPPFunction) binding; + if(func.getRequiredArgumentCount() == 1) { + IType type = null; + if(kind == IASTLiteralExpression.lk_integer_constant) { + type = new CPPBasicType(Kind.eInt, IBasicType.IS_UNSIGNED | IBasicType.IS_LONG_LONG); + } else if(kind == IASTLiteralExpression.lk_float_constant) { + type = new CPPBasicType(Kind.eDouble, IBasicType.IS_LONG); + } + return func.getParameters()[0].getType().isSameType(type); + } + } + return false; + } + + /** * Given a LiteralExpression with a user-defined literal suffix, * finds the corresponding defined operator. * Tries to implement 2.14.8.(2-10) @@ -3168,7 +3187,7 @@ public class CPPSemantics { CPPBasicType t = new CPPBasicType(Kind.eInt, IBasicType.IS_UNSIGNED | IBasicType.IS_LONG_LONG, exp); data.setFunctionArguments(false, createArgForType(exp, t)); ret = resolveFunction(data, funcs, true); - if (ret != null && !(ret instanceof ProblemBinding)) { + if (isViableUserDefinedLiteralOperator(ret, kind)) { return ret; } } else if (kind == IASTLiteralExpression.lk_float_constant) { @@ -3182,7 +3201,7 @@ public class CPPSemantics { CPPBasicType t = new CPPBasicType(Kind.eDouble, IBasicType.IS_LONG, exp); data.setFunctionArguments(false, createArgForType(exp, t)); ret = resolveFunction(data, funcs, true); - if (ret != null && !(ret instanceof ProblemBinding)) { + if (isViableUserDefinedLiteralOperator(ret, kind)) { return ret; } } @@ -3205,28 +3224,28 @@ public class CPPSemantics { // "literal"_op -> operator "" _op<'l', 'i', 't', 'e', 'r', 'a', 'l'>(); ICPPTemplateArgument args[] = new ICPPTemplateArgument[stringLiteral.length]; for (int k = 0; k < stringLiteral.length; k++) { - args[k] = new CPPTemplateNonTypeArgument(new EvalFixed(CPPBasicType.CHAR, PRVALUE, Value.create(stringLiteral[k])), exp); + args[k] = new CPPTemplateNonTypeArgument(new EvalFixed(CPPBasicType.CHAR, PRVALUE, IntegralValue.create(stringLiteral[k])), exp); } data = new LookupData(((CPPASTLiteralExpression) exp).getOperatorName(), args, exp); IBinding litTpl = resolveFunction(data, tplFunctions, true); // Do we have valid template and non-template bindings? - if (ret != null && litTpl != null) { - if (!(ret instanceof IProblemBinding) && litTpl instanceof ICPPFunctionInstance) { + if(ret != null && !(ret instanceof IProblemBinding)) { + // Do we have valid template and non-template bindings? + if(litTpl instanceof ICPPFunctionInstance) { // Ambiguity? It has two valid options, and the spec says it shouldn't - return new ProblemBinding(data.getLookupName(), exp, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, tplFunctions); + return new ProblemBinding(data.getLookupName(), exp, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, tplFunctions); } - - if ((ret instanceof IProblemBinding) && litTpl instanceof ICPPFunctionInstance) { + } else { + if(litTpl instanceof ICPPFunctionInstance) { // Only the template binding is valid ret = litTpl; + } else { + // Couldn't find a valid operator + return ret; } } - else if (ret == null) { - // Couldn't find a valid operator - return new ProblemBinding(data.getLookupName(), exp, IProblemBinding.SEMANTIC_INVALID_OVERLOAD); - } } else if (kind == IASTLiteralExpression.lk_string_literal) { /* * 2.14.8.5 @@ -3257,7 +3276,7 @@ public class CPPSemantics { return ret; } - + static ICPPFunction resolveTargetedFunction(IType targetType, CPPFunctionSet set, IASTNode point) { targetType= getNestedType(targetType, TDEF | REF | CVTYPE | PTR | MPTR); if (!(targetType instanceof ICPPFunctionType)) @@ -3330,7 +3349,7 @@ public class CPPSemantics { public static ICPPFunction findOverloadedOperator(ICPPASTNewExpression expr) { OverloadableOperator op = OverloadableOperator.fromNewExpression(expr); - final ICPPEvaluation evaluation = expr.getEvaluation(); + final ICPPEvaluation evaluation = ((ICPPEvaluationOwner)expr).getEvaluation(); if (evaluation.isTypeDependent()) return null; @@ -3347,7 +3366,7 @@ public class CPPSemantics { args[1]= arg2; int i= 2; for (IASTInitializerClause p : placement) { - final ICPPASTInitializerClause arg = (ICPPASTInitializerClause) p; + final ICPPEvaluationOwner arg = (ICPPEvaluationOwner) p; final ICPPEvaluation a = arg.getEvaluation(); if (a.isTypeDependent()) return null; @@ -3365,8 +3384,8 @@ public class CPPSemantics { return null; ICPPEvaluation[] args = { - new EvalFixed(type, LVALUE, Value.UNKNOWN), - ((ICPPASTExpression) expr.getOperand()).getEvaluation() + new EvalFixed(type, LVALUE, IntegralValue.UNKNOWN), + ((ICPPEvaluationOwner) expr.getOperand()).getEvaluation() }; return findOverloadedOperator(expr, null, args, type, op, LookupMode.GLOBALS_IF_NO_MEMBERS); } @@ -3449,8 +3468,8 @@ public class CPPSemantics { if (initializer instanceof IASTEqualsInitializer) { // Copy initialization. IASTEqualsInitializer eqInit= (IASTEqualsInitializer) initializer; - ICPPASTInitializerClause initClause = (ICPPASTInitializerClause) eqInit.getInitializerClause(); - final ICPPEvaluation evaluation = initClause.getEvaluation(); + ICPPEvaluationOwner evalOwner = (ICPPEvaluationOwner) eqInit.getInitializerClause(); + final ICPPEvaluation evaluation = evalOwner.getEvaluation(); IType sourceType= evaluation.getType(typeId); ValueCategory isLValue= evaluation.getValueCategory(typeId); if (sourceType != null) { @@ -3469,7 +3488,7 @@ public class CPPSemantics { } } else if (initializer instanceof ICPPASTInitializerList) { // List initialization. - ICPPEvaluation eval= ((ICPPASTInitializerList) initializer).getEvaluation(); + ICPPEvaluation eval= ((ICPPEvaluationOwner) initializer).getEvaluation(); if (eval instanceof EvalInitList) { Cost c= Conversions.listInitializationSequence((EvalInitList) eval, type, UDCMode.ALLOWED, true, typeId); if (c.converts()) { @@ -3530,7 +3549,7 @@ public class CPPSemantics { final char[] name = CharArrayUtils.concat("~".toCharArray(), cls.getNameCharArray()); //$NON-NLS-1$ LookupData data = new LookupData(name, null, expr); data.qualified = true; - data.setFunctionArguments(true, new EvalFixed(cls, LVALUE, Value.UNKNOWN)); + data.setFunctionArguments(true, new EvalFixed(cls, LVALUE, IntegralValue.UNKNOWN)); try { lookup(data, scope); IBinding[] found= data.getFoundBindings(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index b7c1950f75e..949c46bd8e2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -122,10 +122,10 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPAliasTemplateInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType; @@ -172,11 +172,15 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMemberClass; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMethod; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclarationSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariableInstance; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariableSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariableTemplate; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariableTemplatePartialSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalTemplateDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPComputableFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluationOwner; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalClassTemplate; @@ -613,7 +617,7 @@ public class CPPTemplates { } else if (tp instanceof ICPPTemplateNonTypeParameter) { // Non-type template parameter pack already has type 'ICPPParameterPackType' final ICPPTemplateNonTypeParameter nttp = (ICPPTemplateNonTypeParameter) tp; - args[i] = new CPPTemplateNonTypeArgument(Value.create(template, nttp), nttp.getType()); + args[i] = new CPPTemplateNonTypeArgument(IntegralValue.create(template, nttp), nttp.getType()); } else { assert false; } @@ -923,7 +927,7 @@ public class CPPTemplates { } else { spec = new CPPFunctionInstance((ICPPFunction) template, owner, tpMap, args, type, exceptionSpecs); } - spec.setParameters(specializeParameters(func.getParameters(), spec, context, Value.MAX_RECURSION_DEPTH)); + spec.setParameters(specializeParameters(func.getParameters(), spec, context, IntegralValue.MAX_RECURSION_DEPTH)); instance = (ICPPTemplateInstance) spec; } else if (template instanceof ICPPVariable) { ICPPVariable var = (ICPPVariable) template; @@ -937,7 +941,7 @@ public class CPPTemplates { // Explicit specialization. value = SemanticUtil.getValueOfInitializer(decl.getInitializer(), type); } else { - value = instantiateValue(var.getInitialValue(), context, Value.MAX_RECURSION_DEPTH); + value = instantiateValue(var.getInitialValue(), context, IntegralValue.MAX_RECURSION_DEPTH); } if (template instanceof ICPPField) { @@ -972,10 +976,27 @@ public class CPPTemplates { } return result; } + + // TODO(nathanridge): Handle this as a case in createSpecialization() + public static ICPPVariable createVariableSpecialization(InstantiationContext context, ICPPVariable variable) { + final IType type = variable.getType(); + final IType newType = instantiateType(type, context); + final IValue value = variable.getInitialValue(); + final IValue newValue = instantiateValue(value, context, IntegralValue.MAX_RECURSION_DEPTH); + if(type == newType && value == newValue) { + return variable; + } + ICPPVariable newVariable = new CPPVariableSpecialization(variable, context.getContextSpecialization(), + context.getParameterMap(), newType, newValue); + context.putInstantiatedLocal(variable, newVariable); + return newVariable; + } - public static IBinding createSpecialization(ICPPClassSpecialization owner, IBinding decl, IASTNode point) { + public static IBinding createSpecialization(ICPPSpecialization owner, IBinding decl, IASTNode point) { IBinding spec = null; final ICPPTemplateParameterMap tpMap= owner.getTemplateParameterMap(); + final ICPPClassSpecialization classOwner = (owner instanceof ICPPClassSpecialization) ? (ICPPClassSpecialization)owner : null; + // Guard against infinite recursion during template instantiation with a depth limit. int instantiationDepth = fTemplateInstantiationDepth.get(); if (instantiationDepth > TEMPLATE_INSTANTIATION_DEPTH_LIMIT) { @@ -983,46 +1004,49 @@ public class CPPTemplates { } // Increment the instantiation depth for the duration of this call. fTemplateInstantiationDepth.set(instantiationDepth + 1); + try { - if (decl instanceof ICPPClassTemplatePartialSpecialization) { + if (decl instanceof ICPPClassTemplatePartialSpecialization && classOwner != null) { try { ICPPClassTemplatePartialSpecialization pspec= (ICPPClassTemplatePartialSpecialization) decl; ICPPClassTemplate template= pspec.getPrimaryClassTemplate(); ICPPTemplateArgument[] args = pspec.getTemplateArguments(); - template= (ICPPClassTemplate) owner.specializeMember(template, point); + + template= (ICPPClassTemplate) classOwner.specializeMember(template, point); InstantiationContext context = createInstantiationContext(tpMap, owner, point); args= instantiateArguments(args, context, false); spec= new CPPClassTemplatePartialSpecializationSpecialization(pspec, tpMap, template, args); } catch (DOMException e) { } - } else if (decl instanceof ICPPClassTemplate) { + } else if (decl instanceof ICPPClassTemplate && classOwner != null) { ICPPClassTemplate template = (ICPPClassTemplate) decl; - CPPClassTemplateSpecialization classTemplateSpec = new CPPClassTemplateSpecialization(template, owner, tpMap); + CPPClassTemplateSpecialization classTemplateSpec = new CPPClassTemplateSpecialization(template, classOwner, tpMap); classTemplateSpec.setTemplateParameters(specializeTemplateParameters(classTemplateSpec, - (ICPPScope) classTemplateSpec.getScope(), template.getTemplateParameters(), owner, point)); + (ICPPScope) classTemplateSpec.getScope(), template.getTemplateParameters(), classOwner, point)); spec = classTemplateSpec; - } else if (decl instanceof ICPPClassType) { + } else if (decl instanceof ICPPClassType && classOwner != null) { + // TODO: Handle local classes IBinding oldOwner = decl.getOwner(); - if (oldOwner instanceof IType && owner.getSpecializedBinding().isSameType((IType) oldOwner)) { + if (oldOwner instanceof IType && classOwner.getSpecializedBinding().isSameType((IType) oldOwner)) { spec = new CPPClassSpecialization((ICPPClassType) decl, owner, tpMap); } else { spec = new CPPClassSpecialization((ICPPClassType) decl, oldOwner, tpMap); } - } else if (decl instanceof ICPPField) { + } else if (decl instanceof ICPPField && classOwner != null) { ICPPField field= (ICPPField) decl; InstantiationContext context = createInstantiationContext(tpMap, owner, point); IType type= instantiateType(field.getType(), context); - IValue value= instantiateValue(field.getInitialValue(), context, Value.MAX_RECURSION_DEPTH); + IValue value= instantiateValue(field.getInitialValue(), context, IntegralValue.MAX_RECURSION_DEPTH); if (decl instanceof ICPPFieldTemplate) { CPPFieldTemplateSpecialization fieldTempSpec = new CPPFieldTemplateSpecialization(decl, - owner, tpMap, type, value); + classOwner, tpMap, type, value); ICPPTemplateParameter[] params = specializeTemplateParameters(fieldTempSpec, (ICPPScope) fieldTempSpec.getScope(), - ((ICPPFieldTemplate) decl).getTemplateParameters(), owner, point); + ((ICPPFieldTemplate) decl).getTemplateParameters(), classOwner, point); fieldTempSpec.setTemplateParameters(params); spec = fieldTempSpec; } else { - spec = new CPPFieldSpecialization(decl, owner, tpMap, type, value); + spec = new CPPFieldSpecialization(decl, classOwner, tpMap, type, value); } } else if (decl instanceof ICPPFunction) { ICPPFunction func= (ICPPFunction) decl; @@ -1032,35 +1056,35 @@ public class CPPTemplates { CPPFunctionSpecialization functionSpec = null; if (decl instanceof ICPPFunctionTemplate) { - if (decl instanceof ICPPMethod) { + if (decl instanceof ICPPMethod && classOwner != null) { CPPMethodTemplateSpecialization methodSpec; if (decl instanceof ICPPConstructor) { methodSpec = new CPPConstructorTemplateSpecialization((ICPPConstructor) decl, - owner, tpMap, type, exceptionSpecs); + classOwner, tpMap, type, exceptionSpecs); } else { - methodSpec = new CPPMethodTemplateSpecialization((ICPPMethod) decl, owner, tpMap, + methodSpec = new CPPMethodTemplateSpecialization((ICPPMethod) decl, classOwner, tpMap, type, exceptionSpecs); } methodSpec.setTemplateParameters(specializeTemplateParameters(methodSpec, (ICPPScope) methodSpec.getScope(), - ((ICPPFunctionTemplate) decl).getTemplateParameters(), owner, point)); + ((ICPPFunctionTemplate) decl).getTemplateParameters(), classOwner, point)); functionSpec = methodSpec; } else { IBinding oldOwner = decl.getOwner(); functionSpec = new CPPFunctionTemplateSpecialization((ICPPFunctionTemplate) decl, oldOwner, tpMap, type, exceptionSpecs); } - } else if (decl instanceof ICPPConstructor) { - functionSpec = new CPPConstructorSpecialization((ICPPConstructor) decl, owner, tpMap, type, exceptionSpecs); - } else if (decl instanceof ICPPMethod) { - functionSpec = new CPPMethodSpecialization((ICPPMethod) decl, owner, tpMap, type, exceptionSpecs); + } else if (decl instanceof ICPPConstructor && classOwner != null) { + functionSpec = new CPPConstructorSpecialization((ICPPConstructor) decl, classOwner, tpMap, type, exceptionSpecs); + } else if (decl instanceof ICPPMethod && classOwner != null) { + functionSpec = new CPPMethodSpecialization((ICPPMethod) decl, classOwner, tpMap, type, exceptionSpecs); } else if (decl instanceof ICPPFunction) { IBinding oldOwner = decl.getOwner(); functionSpec = new CPPFunctionSpecialization((ICPPFunction) decl, oldOwner, tpMap, type, exceptionSpecs); } if (functionSpec != null) { functionSpec.setParameters(specializeParameters(func.getParameters(), functionSpec, context, - Value.MAX_RECURSION_DEPTH)); + IntegralValue.MAX_RECURSION_DEPTH)); } spec = functionSpec; } else if (decl instanceof ITypedef) { @@ -1072,12 +1096,13 @@ public class CPPTemplates { InstantiationContext context = createInstantiationContext(tpMap, owner, point); IType type= instantiateType(aliasTemplate.getType(), context); spec = new CPPAliasTemplateInstance(decl.getNameCharArray(), aliasTemplate, type); - } else if (decl instanceof ICPPEnumeration) { - spec = CPPEnumerationSpecialization.createInstance((ICPPEnumeration) decl, owner, tpMap, point); - } else if (decl instanceof IEnumerator) { + } else if (decl instanceof ICPPEnumeration && classOwner != null) { + // TODO: Handle local enumerations + spec = CPPEnumerationSpecialization.createInstance((ICPPEnumeration) decl, classOwner, tpMap, point); + } else if (decl instanceof IEnumerator && classOwner != null) { IEnumerator enumerator = (IEnumerator) decl; ICPPEnumeration enumeration = (ICPPEnumeration) enumerator.getOwner(); - IBinding enumSpec = owner.specializeMember(enumeration, point); + IBinding enumSpec = classOwner.specializeMember(enumeration, point); if (enumSpec instanceof ICPPEnumerationSpecialization) { spec = ((ICPPEnumerationSpecialization) enumSpec).specializeEnumerator(enumerator); } @@ -1112,7 +1137,7 @@ public class CPPTemplates { return spec; } - private static InstantiationContext createInstantiationContext(ICPPTemplateParameterMap tpMap, + private static InstantiationContext createInstantiationContext(ICPPTemplateParameterMap tpMap, IBinding owner, IASTNode point) { return new InstantiationContext(tpMap, getSpecializationContext(owner), point); } @@ -1315,8 +1340,7 @@ public class CPPTemplates { * {@code false}, any invalid instantiated arguments are replaced by the corresponding original * arguments. */ - public static ICPPTemplateArgument[] instantiateArguments(ICPPTemplateArgument[] args, - InstantiationContext context, boolean strict) throws DOMException { + public static ICPPTemplateArgument[] instantiateArguments(ICPPTemplateArgument[] args, InstantiationContext context, boolean strict) throws DOMException { // Don't create a new array until it's really needed. ICPPTemplateArgument[] result = args; int resultShift= 0; @@ -1395,7 +1419,7 @@ public class CPPTemplates { return null; if (arg.isNonTypeValue()) { final ICPPEvaluation eval = arg.getNonTypeEvaluation(); - final ICPPEvaluation newEval= eval.instantiate(context, Value.MAX_RECURSION_DEPTH); + final ICPPEvaluation newEval= eval.instantiate(context, IntegralValue.MAX_RECURSION_DEPTH); if (eval == newEval) return arg; return new CPPTemplateNonTypeArgument(newEval, context.getPoint()); @@ -1475,7 +1499,7 @@ public class CPPTemplates { if (type instanceof ICPPUnknownBinding) { if (type instanceof TypeOfDependentExpression) { ICPPEvaluation eval = ((TypeOfDependentExpression) type).getEvaluation(); - ICPPEvaluation instantiated = eval.instantiate(context, Value.MAX_RECURSION_DEPTH); + ICPPEvaluation instantiated = eval.instantiate(context, IntegralValue.MAX_RECURSION_DEPTH); if (instantiated != eval) return instantiated.getType(context.getPoint()); } else { @@ -1565,7 +1589,7 @@ public class CPPTemplates { IArrayType at= (IArrayType) typeContainer; IValue asize= at.getSize(); if (asize != null) { - IValue newSize= instantiateValue(asize, context, Value.MAX_RECURSION_DEPTH); + IValue newSize= instantiateValue(asize, context, IntegralValue.MAX_RECURSION_DEPTH); if (newSize != asize) { return new CPPArrayType(newNestedType, newSize); } @@ -2142,7 +2166,7 @@ public class CPPTemplates { result[i]= new CPPTemplateTypeArgument(CPPVisitor.createType((IASTTypeId) arg)); } else if (arg instanceof ICPPASTExpression) { ICPPASTExpression expr= (ICPPASTExpression) arg; - result[i]= new CPPTemplateNonTypeArgument(expr.getEvaluation(), expr); + result[i]= new CPPTemplateNonTypeArgument(((ICPPEvaluationOwner)expr).getEvaluation(), expr); } else if (arg instanceof ICPPASTAmbiguousTemplateArgument) { IProblemBinding problem = new ProblemBinding(id, IProblemBinding.SEMANTIC_INVALID_TEMPLATE_ARGUMENTS); throw new DOMException(problem); @@ -2376,7 +2400,7 @@ public class CPPTemplates { private static ICPPTemplateArgument uniqueArg(final ICPPTemplateParameter tpar) throws DOMException { final ICPPTemplateArgument arg; if (tpar instanceof ICPPTemplateNonTypeParameter) { - arg = new CPPTemplateNonTypeArgument(Value.unique(), ((ICPPTemplateNonTypeParameter) tpar).getType()); + arg = new CPPTemplateNonTypeArgument(IntegralValue.unique(), ((ICPPTemplateNonTypeParameter) tpar).getType()); } else { arg = new CPPTemplateTypeArgument(new UniqueType(tpar.isParameterPack())); } @@ -2420,8 +2444,8 @@ public class CPPTemplates { args= new IType[] {transFt1.getReturnType()}; break; case PARAMETERS_AND_RETURN_TYPE: - pars= concat(ft2.getReturnType(), ft2.getParameterTypes()); - args= concat(transFt1.getReturnType(), transFt1.getParameterTypes()); + pars= SemanticUtil.concatTypes(ft2.getReturnType(), ft2.getParameterTypes()); + args= SemanticUtil.concatTypes(transFt1.getReturnType(), transFt1.getParameterTypes()); break; case PARAMETERS: default: @@ -2431,9 +2455,9 @@ public class CPPTemplates { boolean nonStaticMember2= isNonStaticMember(f2); if (nonStaticMember1 != nonStaticMember2) { if (nonStaticMember1) { - args= addImplicitParameterType(args, (ICPPMethod) f1); + args= SemanticUtil.addImplicitParameterType(args, (ICPPMethod) f1); } else { - pars= addImplicitParameterType(pars, (ICPPMethod) f2); + pars= SemanticUtil.addImplicitParameterType(pars, (ICPPMethod) f2); } } break; @@ -2445,22 +2469,6 @@ public class CPPTemplates { return (f instanceof ICPPMethod) && !((ICPPMethod) f).isStatic(); } - private static IType[] addImplicitParameterType(IType[] types, ICPPMethod m) { - try { - IType t= CPPSemantics.getImplicitParameterType(m); - return concat(t, types); - } catch (DOMException e) { - return types; - } - } - - private static IType[] concat(final IType t, IType[] types) { - IType[] result= new IType[types.length+1]; - result[0]= t; - System.arraycopy(types, 0, result, 1, types.length); - return result; - } - private static ICPPPartialSpecialization findPartialSpecialization(ICPPPartiallySpecializable ct, ICPPTemplateArgument[] args) throws DOMException { ICPPPartialSpecialization[] pspecs = ct.getPartialSpecializations(); @@ -2787,7 +2795,7 @@ public class CPPTemplates { return false; if (par.isParameterPack() != arg.isPackExpansion()) return false; - int parpos= Value.isTemplateParameter(arg.getNonTypeValue()); + int parpos= IntegralValue.isTemplateParameter(arg.getNonTypeValue()); if (parpos != par.getParameterID()) return false; } @@ -2847,7 +2855,7 @@ public class CPPTemplates { } else if (t instanceof ITypeContainer) { if (t instanceof IArrayType) { IValue asize= ((IArrayType) t).getSize(); - if (asize != null && Value.isDependentValue(asize)) + if (asize != null && IntegralValue.isDependentValue(asize)) return true; } t= ((ITypeContainer) t).getType(); @@ -2954,8 +2962,7 @@ public class CPPTemplates { return result; } - private static IBinding resolveDeferredClassInstance(ICPPDeferredClassInstance dci, - InstantiationContext context) { + private static IBinding resolveDeferredClassInstance(ICPPDeferredClassInstance dci, InstantiationContext context) { ICPPClassTemplate classTemplate = dci.getClassTemplate(); ICPPTemplateArgument[] arguments = dci.getTemplateArguments(); ICPPTemplateArgument[] newArgs; @@ -3063,4 +3070,56 @@ public class CPPTemplates { } return binding; } + + /** + * Returns the instantiated function body of the given function specialization. + * @param point The point of instantiation for name lookups + */ + public static ICPPExecution instantiateFunctionBody(T f, + IASTNode point) { + ICPPFunction spec = (ICPPFunction) f.getSpecializedBinding(); + ICPPExecution exec = null; + if (spec instanceof ICPPComputableFunction) { + exec = ((ICPPComputableFunction) spec).getFunctionBodyExecution(point); + if (exec != null) { + InstantiationContext context = new InstantiationContext(f.getTemplateParameterMap(), f, point); + CPPTemplates.addInstantiatedParameters(context, f); + exec = exec.instantiate(context, IntegralValue.MAX_RECURSION_DEPTH); + } + } + return exec; + } + + private static void addInstantiatedParameters( + InstantiationContext context, T spec) { + ICPPFunction specialized = (ICPPFunction) spec.getSpecializedBinding(); + ICPPParameter paramSpecs[] = spec.getParameters(); + ICPPParameter specializedParams[] = specialized.getParameters(); + for(int i = 0; i < paramSpecs.length; i++) { + final ICPPParameter paramSpecialization = paramSpecs[i]; + final ICPPParameter specializedParam = specializedParams[i]; + context.putInstantiatedLocal(specializedParam, paramSpecialization); + if(specializedParam.isParameterPack()) { + break; + } + } + } + + /** + * Returns the instantiated constructor chain of the given constructor specialization. + * @param point The point of instantiation for name lookups + */ + public static ICPPExecution instantiateConstructorChain( + T f, IASTNode point) { + ICPPConstructor spec = (ICPPConstructor) f.getSpecializedBinding(); + ICPPExecution exec = null; + if (spec != null) { + exec = spec.getConstructorChainExecution(point); + if (exec != null) { + InstantiationContext context = new InstantiationContext(f.getTemplateParameterMap(), f, point); + exec = exec.instantiate(context, IntegralValue.MAX_RECURSION_DEPTH); + } + } + return exec; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 60241a7b9e3..55fe872626c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -178,10 +178,10 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionCallExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression; @@ -221,6 +221,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownTypeScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariableTemplate; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluationOwner; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; @@ -1990,9 +1991,9 @@ public class CPPVisitor extends ASTQueries { IASTInitializerClause clause = ((IASTEqualsInitializer) initializer).getInitializerClause(); if (clause instanceof IASTInitializerList) { IASTInitializerClause[] clauses = ((IASTInitializerList) clause).getClauses(); - sizeValue = Value.create(clauses.length); + sizeValue = IntegralValue.create(clauses.length); } else if (clause instanceof ICPPASTLiteralExpression) { - ICPPEvaluation value = ((ICPPASTLiteralExpression) clause).getEvaluation(); + ICPPEvaluation value = ((ICPPEvaluationOwner) clause).getEvaluation(); IType valueType = value.getType(clause); if (valueType instanceof IArrayType) { sizeValue = ((IArrayType) valueType).getSize(); @@ -2052,7 +2053,7 @@ public class CPPVisitor extends ASTQueries { if (t instanceof IArrayType) { IArrayType at= (IArrayType) t; if (at.getSize() == null) { - type= new CPPArrayType(at.getType(), Value.create(((IASTInitializerList) initClause).getSize())); + type= new CPPArrayType(at.getType(), IntegralValue.create(((IASTInitializerList) initClause).getSize())); } } } @@ -2197,7 +2198,7 @@ public class CPPVisitor extends ASTQueries { } } type = decorateType(type, declSpec, declarator); - final ICPPEvaluation evaluation = initClause.getEvaluation(); + final ICPPEvaluation evaluation = ((ICPPEvaluationOwner)initClause).getEvaluation(); initType= evaluation.getType(declarator); valueCat= evaluation.getValueCategory(declarator); if (initType == null || initType instanceof ISemanticProblem) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index 227d06c0e77..7e234767e5a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -339,7 +339,7 @@ public class Conversions { static Cost listInitializationSequenceHelper(EvalInitList arg, IType target, UDCMode udc, boolean isDirect, IASTNode point) throws DOMException { IType listType= getInitListType(target); if (listType == null && target instanceof IArrayType) { - Long arraySize = ((IArrayType) target).getSize().numericalValue(); + Number arraySize = ((IArrayType) target).getSize().numberValue(); if (arraySize != null) { IType elementType = ((IArrayType) target).getType(); // TODO(nathanridge): If there are fewer initializer clauses than the array size, diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java index 43398fd7e06..12260e4863f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java @@ -220,10 +220,12 @@ public class Cost { IArrayType arrayType = (IArrayType) fListInitializationTarget; IArrayType otherArrayType = (IArrayType) other.fListInitializationTarget; if (arrayType.getType().isSameType(otherArrayType.getType())) { - Long size = arrayType.getSize().numericalValue(); - Long otherSize = otherArrayType.getSize().numericalValue(); + Number size = arrayType.getSize().numberValue(); + Number otherSize = otherArrayType.getSize().numberValue(); if (size != null && otherSize != null) { - return size.compareTo(otherSize); + Long a = size.longValue(); + Long b = otherSize.longValue(); + return a.compareTo(b); } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java index 996b5e50775..18757a56829 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java @@ -12,6 +12,36 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.*; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryAnd; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryAndAssign; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryOr; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryOrAssign; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryXor; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryXorAssign; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_divide; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_divideAssign; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_equals; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_greaterEqual; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_greaterThan; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_lessEqual; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_lessThan; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_logicalAnd; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_logicalOr; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_minus; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_minusAssign; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_modulo; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_moduloAssign; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_multiply; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_multiplyAssign; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_notequals; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_plus; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_plusAssign; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_pmarrow; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_pmdot; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftLeft; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftLeftAssign; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftRight; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftRightAssign; import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE; import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.glvalueType; @@ -25,6 +55,8 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IArrayType; +import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.ISemanticProblem; @@ -33,12 +65,14 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArithmeticConversion; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; @@ -46,6 +80,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil.Pair; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; @@ -60,6 +95,7 @@ public class EvalBinary extends CPPDependentEvaluation { private final ICPPEvaluation fArg2; private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; + private ICPPEvaluation fOverloadCall; private IType fType; private boolean fCheckedIsConstantExpression; private boolean fIsConstantExpression; @@ -115,6 +151,20 @@ public class EvalBinary extends CPPDependentEvaluation { } return fType; } + + private ICPPEvaluation createOperatorOverloadEvaluation(ICPPFunction overload, IASTNode point, ICPPEvaluation arg1, ICPPEvaluation arg2) { + EvalFunctionCall operatorCall; + if(overload instanceof ICPPMethod) { + EvalMemberAccess opAccess = new EvalMemberAccess(arg1.getType(point), ValueCategory.LVALUE, overload, arg1, false, point); + ICPPEvaluation[] args = new ICPPEvaluation[]{opAccess, arg2}; + operatorCall = new EvalFunctionCall(args, arg1, point); + } else { + EvalBinding op = new EvalBinding(overload, overload.getType(), point); + ICPPEvaluation[] args = new ICPPEvaluation[]{op, arg1, arg2}; + operatorCall = new EvalFunctionCall(args, null, point); + } + return operatorCall; + } @Override public IValue getValue(IASTNode point) { @@ -122,8 +172,7 @@ public class EvalBinary extends CPPDependentEvaluation { ICPPEvaluation arg2 = fArg2; ICPPFunction overload = getOverload(point); if (overload != null) { - ICPPFunctionType functionType = overload.getType(); - IType[] parameterTypes = functionType.getParameterTypes(); + IType[] parameterTypes = SemanticUtil.getParameterTypesIncludingImplicitThis(overload); if (parameterTypes.length >= 2) { arg1 = maybeApplyConversion(fArg1, parameterTypes[0], point); arg2 = maybeApplyConversion(fArg2, parameterTypes[1], point); @@ -133,47 +182,52 @@ public class EvalBinary extends CPPDependentEvaluation { } if (!(overload instanceof CPPImplicitFunction)) { - if (!overload.isConstexpr()) - return Value.ERROR; - ICPPEvaluation eval = new EvalBinding(overload, null, (IBinding) null); - ICPPEvaluation call = - new EvalFunctionCall(new ICPPEvaluation[] {eval, arg1, arg2}, (IBinding) null); - return call.getValue(point); + if (!overload.isConstexpr()) { + return IntegralValue.ERROR; + } + if (fOverloadCall == null) { + fOverloadCall = createOperatorOverloadEvaluation(overload, point, arg1, arg2); + } + return fOverloadCall.getValue(point); } } IValue v1 = arg1.getValue(point); - if (v1 == null || v1 == Value.UNKNOWN) - return Value.UNKNOWN; + if (v1 == null || v1 == IntegralValue.UNKNOWN) + return IntegralValue.UNKNOWN; IValue v2 = arg2.getValue(point); - if (v2 == null || v2 == Value.UNKNOWN) - return Value.UNKNOWN; + if (v2 == null || v2 == IntegralValue.UNKNOWN) + return IntegralValue.UNKNOWN; switch (fOperator) { case op_equals: if (v1.equals(v2)) - return Value.create(1); + return IntegralValue.create(true); break; case op_notequals: if (v1.equals(v2)) - return Value.create(0); + return IntegralValue.create(false); break; + case op_assign: + return v2; } - Long num1 = v1.numericalValue(); + Number num1 = v1.numberValue(); if (num1 != null) { - if (num1 == 0) { - if (fOperator == op_logicalAnd) + if (num1 instanceof Long && num1.longValue() == 0) { + if (fOperator == op_logicalAnd) { return v1; + } } else if (fOperator == op_logicalOr) { return v1; } - Long num2 = v2.numericalValue(); + + Number num2 = v2.numberValue(); if (num2 != null) { - return Value.evaluateBinaryExpression(fOperator, num1, num2); + return ValueFactory.evaluateBinaryExpression(fOperator, v1, v2); } } - return Value.create(this); + return IntegralValue.create(this); } @Override @@ -252,7 +306,7 @@ public class EvalBinary extends CPPDependentEvaluation { private ICPPFunction computeOverload(IASTNode point) { if (isTypeDependent()) return null; - + if (fOperator == op_arrayAccess) { IType type = fArg1.getType(point); type= SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); @@ -374,13 +428,134 @@ public class EvalBinary extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { - ICPPEvaluation arg1 = fArg1.computeForFunctionCall(parameterMap, context.recordStep()); - ICPPEvaluation arg2 = fArg2.computeForFunctionCall(parameterMap, context.recordStep()); - if (arg1 == fArg1 && arg2 == fArg2) - return this; - return new EvalBinary(fOperator, arg1, arg2, getTemplateDefinition()); + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPFunction overload = getOverload(context.getPoint()); + if (overload != null) { + ICPPEvaluation operatorCall = createOperatorOverloadEvaluation(overload, context.getPoint(), fArg1, fArg2); + return operatorCall.computeForFunctionCall(record, context); + } + + Pair vp1 = EvalUtil.getValuePair(fArg1, record, context); + final ICPPEvaluation updateable1 = vp1.getFirst(); + final ICPPEvaluation fixed1 = vp1.getSecond(); + Pair vp2 = EvalUtil.getValuePair(fArg2, record, context); + final ICPPEvaluation fixed2 = vp2.getSecond(); + ICPPEvaluation eval = fixed1 == fArg1 && fixed2 == fArg2 ? this : new EvalBinary(fOperator, fixed1, fixed2, getTemplateDefinition()); + + if(isBinaryOperationWithAssignment(fOperator)) { + if (isPointerToArray(fixed1) && hasIntType(fixed2, context)) { + EvalPointer evalPointer = (EvalPointer)fixed1; + int currentPos = evalPointer.getPosition(); + int rhs = fixed2.getValue(context.getPoint()).numberValue().intValue(); + + if(fOperator == op_plusAssign) { + evalPointer.setPosition(currentPos + rhs); + } else if(fOperator == op_minusAssign) { + evalPointer.setPosition(currentPos - rhs); + } else { + return EvalFixed.INCOMPLETE; + } + } else { + int binaryOperator = getBinaryOperatorWithoutAssignment(fOperator); + EvalBinary binaryOpEval = new EvalBinary(binaryOperator, fixed1, fixed2, getTemplateDefinition()); + EvalBinary assignmentEval = new EvalBinary(op_assign, updateable1, binaryOpEval, getTemplateDefinition()); + return assignmentEval.computeForFunctionCall(record, context); + } + } else if(fOperator == op_assign) { + ICPPEvaluation newValue = null; + if(fixed2 instanceof EvalPointer) { + newValue = fixed2; + } else { + newValue = new EvalFixed(fixed2.getType(context.getPoint()), fixed2.getValueCategory(context.getPoint()), fixed2.getValue(context.getPoint())); + } + + if (updateable1 instanceof EvalReference && !(updateable1 instanceof EvalPointer)) { + EvalReference evalRef = (EvalReference)updateable1; + evalRef.update(newValue); + } else if (updateable1 instanceof EvalCompositeAccess) { + EvalCompositeAccess evalCompAccess = (EvalCompositeAccess)updateable1; + evalCompAccess.update(newValue); + } else if (updateable1 instanceof EvalBinding) { + EvalBinding evalBinding = (EvalBinding)updateable1; + record.update(evalBinding.getBinding(), newValue); + } + return updateable1; + } else if (fOperator == op_arrayAccess) { + return new EvalCompositeAccess(fixed1, fixed2.getValue(context.getPoint()).numberValue().intValue()); + } else if ((isArray(fixed1, context) || isArray(fixed2, context)) && (hasIntType(fixed1, context) || hasIntType(fixed2, context))) { + int offset = hasIntType(fixed1, context) ? fixed1.getValue(context.getPoint()).numberValue().intValue() : fixed2.getValue(context.getPoint()).numberValue().intValue(); + EvalCompositeAccess evalCompositeAccess = new EvalCompositeAccess(isArray(fixed1, context) ? fixed1 : fixed2, offset); + return new EvalPointer(record, evalCompositeAccess, evalCompositeAccess.getTemplateDefinition()); + } else if ((isPointerToArray(fixed1) || isPointerToArray(fixed2)) && (hasIntType(fixed1, context) || hasIntType(fixed2, context))) { + final EvalPointer pointer = isPointerToArray(fixed1) ? ((EvalPointer) fixed1).copy() : ((EvalPointer) fixed2).copy(); + pointer.setPosition(eval.getValue(context.getPoint()).numberValue().intValue()); + return pointer; + } + return eval; + } + + private boolean hasIntType(ICPPEvaluation arg2, ConstexprEvaluationContext context) { + IType type = arg2.getType(context.getPoint()); + return (type instanceof IBasicType && ((IBasicType) type).getKind() == IBasicType.Kind.eInt); + } + + private boolean isArray(ICPPEvaluation eval, ConstexprEvaluationContext context) { + return eval.getType(context.getPoint()) instanceof IArrayType; + } + + private boolean isPointerToArray(ICPPEvaluation argument) { + if (argument instanceof EvalPointer) { + EvalPointer evalPointer = (EvalPointer) argument; + ICPPEvaluation pointerValue = evalPointer.dereference().getTargetEvaluation(); + // TODO(nathanridge): What if the composite being accessed is not an array but a structure? + return pointerValue instanceof EvalCompositeAccess; + } + return false; + } + + private static boolean isBinaryOperationWithAssignment(int operator) { + switch (operator) { + case op_binaryAndAssign: + case op_binaryOrAssign: + case op_binaryXorAssign: + case op_divideAssign: + case op_plusAssign: + case op_minusAssign: + case op_multiplyAssign: + case op_moduloAssign: + case op_shiftLeftAssign: + case op_shiftRightAssign: + return true; + default: + return false; + } + } + + private static int getBinaryOperatorWithoutAssignment(int operator) { + switch (operator) { + case op_binaryAndAssign: + return op_binaryAnd; + case op_binaryOrAssign: + return op_binaryOr; + case op_binaryXorAssign: + return op_binaryXor; + case op_divideAssign: + return op_divide; + case op_plusAssign: + return op_plus; + case op_minusAssign: + return op_minus; + case op_multiplyAssign: + return op_multiply; + case op_moduloAssign: + return op_modulo; + case op_shiftLeftAssign: + return op_shiftLeft; + case op_shiftRightAssign: + return op_shiftRight; + default: + throw new IllegalArgumentException("Operator must be binary operation with assignment"); //$NON-NLS-1$ + } } @Override @@ -392,4 +567,9 @@ public class EvalBinary extends CPPDependentEvaluation { public boolean referencesTemplateParameter() { return fArg1.referencesTemplateParameter() || fArg2.referencesTemplateParameter(); } + + @Override + public String toString() { + return fArg1.toString() + " " + fArg2.toString(); //$NON-NLS-1$ + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java index b26810f697f..0344a91cd59 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java @@ -22,8 +22,9 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; @@ -85,9 +86,9 @@ public class EvalBinaryTypeId extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { if (isValueDependent()) - return Value.create(this); + return IntegralValue.create(this); - return Value.evaluateBinaryTypeIdExpression(fOperator, fType1, fType2, point); + return ValueFactory.evaluateBinaryTypeIdExpression(fOperator, fType1, fType2, point); } @Override @@ -141,8 +142,7 @@ public class EvalBinaryTypeId extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { return this; } 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 736f1c4727a..4410de4ff91 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 @@ -37,13 +37,15 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameter; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; @@ -224,13 +226,13 @@ public class EvalBinding extends CPPDependentEvaluation { private boolean computeIsValueDependent() { // No need to call getBinding() since a function parameter never has an initial value. if (fBinding instanceof IEnumerator) { - return Value.isDependentValue(((IEnumerator) fBinding).getValue()); + return IntegralValue.isDependentValue(((IEnumerator) fBinding).getValue()); } if (fBinding instanceof ICPPTemplateNonTypeParameter) { return true; } if (fBinding instanceof IVariable) { - return Value.isDependentValue(((IVariable) fBinding).getInitialValue()); + return IntegralValue.isDependentValue(((IVariable) fBinding).getInitialValue()); } if (fBinding instanceof ICPPUnknownBinding) { return true; @@ -323,17 +325,21 @@ public class EvalBinding extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { if (isValueDependent()) - return Value.create(this); + return IntegralValue.create(this); IValue value= null; - // No need to call getBinding() since a function parameter never has an initial value. - if (fBinding instanceof IVariable) { - value= ((IVariable) fBinding).getInitialValue(); + + if(fBinding instanceof ICPPVariable) { + ICPPEvaluation valueEval = EvalUtil.getVariableValue((ICPPVariable)fBinding, + new ActivationRecord()); + if(valueEval != null) { + value = valueEval.getValue(point); + } } else if (fBinding instanceof IEnumerator) { value= ((IEnumerator) fBinding).getValue(); } if (value == null) - value = Value.UNKNOWN; + value = IntegralValue.UNKNOWN; return value; } @@ -386,22 +392,45 @@ public class EvalBinding extends CPPDependentEvaluation { @Override public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { IBinding origBinding = getBinding(); - if (origBinding instanceof ICPPTemplateNonTypeParameter) { - if (context != null) { - ICPPTemplateArgument argument = context.getArgument((ICPPTemplateNonTypeParameter) origBinding); - if (argument != null && argument.isNonTypeValue()) { - return argument.getNonTypeEvaluation(); + final CPPTemplateParameterMap tpMap = (CPPTemplateParameterMap)context.getParameterMap(); + final int packOffset = context.getPackOffset(); + + IVariable newBinding = tpMap == null ? null : (IVariable)context.getInstantiatedLocal(origBinding); + if(newBinding != null) { + IType origType = ((IVariable)origBinding).getType(); + EvalBinding newBindingEval = null; + if(origType instanceof ICPPParameterPackType) { + origType = ((ICPPParameterPackType) origType).getType(); + IType instantiatedType = CPPTemplates.instantiateType(origType, context); + if(origType != instantiatedType) { + newBindingEval = new EvalBinding(newBinding, instantiatedType, getTemplateDefinition()); } } + + if(newBindingEval == null) { + newBindingEval = new EvalBinding(newBinding, newBinding.getType(), getTemplateDefinition()); + } + if(context.hasPackOffset()) { + return new EvalCompositeAccess(newBindingEval, packOffset); + } else { + return newBindingEval; + } + } + + if (origBinding instanceof ICPPTemplateNonTypeParameter) { + ICPPTemplateArgument argument = context.getArgument((ICPPTemplateNonTypeParameter) origBinding); + if (argument != null && argument.isNonTypeValue()) { + return argument.getNonTypeEvaluation(); + } } else if (origBinding instanceof ICPPParameter) { - ICPPParameter parameter = (ICPPParameter) origBinding; + ICPPParameter parameter = (ICPPParameter) origBinding; IType origType = parameter.getType(); if (origType instanceof ICPPParameterPackType && context.hasPackOffset()) { origType = ((ICPPParameterPackType) origType).getType(); } IType instantiatedType = CPPTemplates.instantiateType(origType, context); if (origType != instantiatedType) { - return new EvalFixed(instantiatedType, ValueCategory.LVALUE, Value.create(this)); + return new EvalFixed(instantiatedType, ValueCategory.LVALUE, IntegralValue.create(this)); } } else { IBinding instantiatedBinding = instantiateBinding(origBinding, context, maxDepth); @@ -412,15 +441,14 @@ public class EvalBinding extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { - int pos = getFunctionParameterPosition(); - if (pos >= 0) { - ICPPEvaluation eval = parameterMap.getArgument(pos); - if (eval != null) - return eval; + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPEvaluation eval = record.getVariable(getBinding()); + + if(eval != null) { + return eval; + } else { + return this; } - return this; } @Override @@ -461,4 +489,9 @@ public class EvalBinding extends CPPDependentEvaluation { // represents a template parameter. return fBinding instanceof ICPPTemplateParameter; } + + @Override + public String toString() { + return getBinding().toString(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java index 8c77dd507ea..10da37f3283 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java @@ -24,7 +24,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.core.runtime.CoreException; @@ -119,7 +119,7 @@ public class EvalComma extends CPPDependentEvaluation { e1= e2; } else { overloads[i - 1] = overload; - e1= new EvalFixed(typeFromFunctionCall(overload), valueCategoryFromFunctionCall(overload), Value.UNKNOWN); + e1= new EvalFixed(typeFromFunctionCall(overload), valueCategoryFromFunctionCall(overload), IntegralValue.UNKNOWN); if (e1.getType(point) instanceof ISemanticProblem) { e1= e2; } @@ -155,7 +155,7 @@ public class EvalComma extends CPPDependentEvaluation { ICPPFunction[] overloads = getOverloads(point); if (overloads.length > 0) { // TODO(sprigogin): Simulate execution of a function call. - return Value.create(this); + return IntegralValue.create(this); } return fArguments[fArguments.length - 1].getValue(point); @@ -212,11 +212,10 @@ public class EvalComma extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { ICPPEvaluation[] args = fArguments; for (int i = 0; i < fArguments.length; i++) { - ICPPEvaluation arg = fArguments[i].computeForFunctionCall(parameterMap, context.recordStep()); + ICPPEvaluation arg = fArguments[i].computeForFunctionCall(record, context.recordStep()); if (arg != fArguments[i]) { if (args == fArguments) { args = new ICPPEvaluation[fArguments.length]; @@ -225,9 +224,11 @@ public class EvalComma extends CPPDependentEvaluation { args[i] = arg; } } - if (args == fArguments) + if (args == fArguments) { return this; - return new EvalComma(args, getTemplateDefinition()); + } + EvalComma evalComma = new EvalComma(args, getTemplateDefinition()); + return evalComma; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompositeAccess.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompositeAccess.java new file mode 100644 index 00000000000..67de1ad2b69 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompositeAccess.java @@ -0,0 +1,165 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; + +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IArrayType; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.ICompositeType; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFunctionCall.ParameterPackType; +import org.eclipse.core.runtime.CoreException; + +/** + * Represents an access to a sub-value of a composite value, identified by an index. + * Composite values can include arrays, structures, and parameter packs (see {@code CompositeValue}). + */ +public class EvalCompositeAccess implements ICPPEvaluation { + private final ICPPEvaluation parent; // the composite value being accessed + private final int elementId; // the index of the sub-value being accessed + + public EvalCompositeAccess(ICPPEvaluation parent, int elementId) { + this.parent = parent; + this.elementId = elementId; + } + + public void update(ICPPEvaluation newValue) { + parent.getValue(null).setSubValue(getElementId(), newValue); + } + + @Override + public boolean isInitializerList() { + return getTargetEvaluation().isInitializerList(); + } + + private ICPPEvaluation getTargetEvaluation() { + return getParent().getValue(null).getSubValue(getElementId()); + } + + @Override + public boolean isFunctionSet() { + return getTargetEvaluation().isFunctionSet(); + } + + @Override + public boolean isTypeDependent() { + return getTargetEvaluation().isTypeDependent(); + } + + @Override + public boolean isValueDependent() { + return getTargetEvaluation().isValueDependent(); + } + + @Override + public boolean isConstantExpression(IASTNode point) { + return getTargetEvaluation().isConstantExpression(point); + } + + @Override + public IType getType(IASTNode point) { + IType type = getParent().getType(point); + type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); + + if(type instanceof IArrayType) { + IArrayType arrayType = (IArrayType)type; + return arrayType.getType(); + } else if(type instanceof InitializerListType) { + InitializerListType initListType = (InitializerListType)type; + return initListType.getEvaluation().getClauses()[getElementId()].getType(point); + } else if(type instanceof ICompositeType) { + ICompositeType compositeType = (ICompositeType)type; + return compositeType.getFields()[getElementId()].getType(); + } else if(type instanceof ParameterPackType) { + ParameterPackType parameterPackType = (ParameterPackType)type; + return parameterPackType.getTypes()[getElementId()]; + } else if(type instanceof ICPPBasicType) { + return type; + } + return null; + } + + @Override + public IValue getValue(IASTNode point) { + return getTargetEvaluation().getValue(null); + } + + @Override + public ValueCategory getValueCategory(IASTNode point) { + return getTargetEvaluation().getValueCategory(point); + } + + @Override + public char[] getSignature() { + return getTargetEvaluation().getSignature(); + } + + @Override + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + if(getTargetEvaluation() != EvalFixed.INCOMPLETE) { + return getTargetEvaluation().computeForFunctionCall(record, context); + } else { + ICPPEvaluation evaluatedComposite = parent.computeForFunctionCall(record, context); + return evaluatedComposite.getValue(context.getPoint()).getSubValue(getElementId()).computeForFunctionCall(record, context); + } + } + + @Override + public int determinePackSize(ICPPTemplateParameterMap tpMap) { + return getTargetEvaluation().determinePackSize(tpMap); + } + + @Override + public boolean referencesTemplateParameter() { + return getTargetEvaluation().referencesTemplateParameter(); + } + + @Override + public IBinding getTemplateDefinition() { + return parent.getTemplateDefinition(); + } + + public ICPPEvaluation getParent() { + return parent; + } + + public int getElementId() { + return elementId; + } + + @Override + public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { + return getTargetEvaluation().instantiate(context, maxDepth); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EVAL_COMPOSITE_ACCESS); + buffer.marshalEvaluation(parent, includeValue); + buffer.putInt(elementId); + } + + public static ISerializableEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPEvaluation parent = (ICPPEvaluation)buffer.unmarshalEvaluation(); + int elementId = buffer.getInt(); + return new EvalCompositeAccess(parent, elementId); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompoundStatementExpression.java similarity index 75% rename from core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java rename to core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompoundStatementExpression.java index a8ec95d066b..02e8855a2e3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompoundStatementExpression.java @@ -29,14 +29,18 @@ import org.eclipse.core.runtime.CoreException; * Performs evaluation of a compound statement expression. Most but not all methods * delegate to the evaluation of the last expression in the compound one. */ -public class EvalCompound extends CPPDependentEvaluation { +public class EvalCompoundStatementExpression extends CPPDependentEvaluation { + // fDelegate is the expression inside the expression-statement which is the + // last statement inside the statement-expression. + // TODO: Store the executions of the statements that come before the last one, + // and simulate their execution in computeForFunctionCall(). private final ICPPEvaluation fDelegate; - public EvalCompound(ICPPEvaluation delegate, IASTNode pointOfDefinition) { + public EvalCompoundStatementExpression(ICPPEvaluation delegate, IASTNode pointOfDefinition) { this(delegate, findEnclosingTemplate(pointOfDefinition)); } - public EvalCompound(ICPPEvaluation delegate, IBinding templateDefinition) { + public EvalCompoundStatementExpression(ICPPEvaluation delegate, IBinding templateDefinition) { super(templateDefinition); fDelegate= delegate; } @@ -95,7 +99,7 @@ public class EvalCompound extends CPPDependentEvaluation { public static ISerializableEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { ICPPEvaluation arg= (ICPPEvaluation) buffer.unmarshalEvaluation(); IBinding templateDefinition= buffer.unmarshalBinding(); - return new EvalCompound(arg, templateDefinition); + return new EvalCompoundStatementExpression(arg, templateDefinition); } @Override @@ -103,16 +107,18 @@ public class EvalCompound extends CPPDependentEvaluation { ICPPEvaluation delegate = fDelegate.instantiate(context, maxDepth); if (delegate == fDelegate) return this; - return new EvalCompound(delegate, getTemplateDefinition()); + return new EvalCompoundStatementExpression(delegate, getTemplateDefinition()); } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { - ICPPEvaluation delegate = fDelegate.computeForFunctionCall(parameterMap, context.recordStep()); - if (delegate == fDelegate) + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPEvaluation delegate = fDelegate.computeForFunctionCall(record, context.recordStep()); + if(delegate == fDelegate) { return this; - return new EvalCompound(delegate, getTemplateDefinition()); + } else { + EvalCompoundStatementExpression evalCompound = new EvalCompoundStatementExpression(delegate, getTemplateDefinition()); + return evalCompound; + } } @Override @@ -124,4 +130,4 @@ public class EvalCompound extends CPPDependentEvaluation { public boolean referencesTemplateParameter() { return fDelegate.referencesTemplateParameter(); } -} \ No newline at end of file +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java index a56955378af..d5d61fea67d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java @@ -33,8 +33,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArithmeticConversion; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; @@ -118,9 +118,9 @@ public class EvalConditional extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { IValue condValue = fCondition.getValue(point); - if (condValue == Value.UNKNOWN) - return Value.UNKNOWN; - Long cond = condValue.numericalValue(); + if (condValue == IntegralValue.UNKNOWN) + return IntegralValue.UNKNOWN; + Number cond = condValue.numberValue(); if (cond != null) { if (cond.longValue() != 0) { return fPositive == null ? condValue : fPositive.getValue(point); @@ -128,7 +128,7 @@ public class EvalConditional extends CPPDependentEvaluation { return fNegative.getValue(point); } } - return Value.create(this); + return IntegralValue.create(this); } @Override @@ -362,27 +362,29 @@ public class EvalConditional extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { - ICPPEvaluation condition = fCondition.computeForFunctionCall(parameterMap, context.recordStep()); + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPEvaluation condition = fCondition.computeForFunctionCall(record, context.recordStep()); // If the condition can be evaluated, fold the conditional into // just the branch that is taken. This avoids infinite recursion // when computing a recursive constexpr function where the base // case of the recursion is one of the branches of the conditional. - Long conditionValue = condition.getValue(context.getPoint()).numericalValue(); + Number conditionValue = condition.getValue(context.getPoint()).numberValue(); if (conditionValue != null) { if (conditionValue.longValue() != 0) { - return fPositive == null ? null : fPositive.computeForFunctionCall(parameterMap, context.recordStep()); + return fPositive == null ? null : fPositive.computeForFunctionCall(record, context.recordStep()); } else { - return fNegative.computeForFunctionCall(parameterMap, context.recordStep()); + return fNegative.computeForFunctionCall(record, context.recordStep()); } } ICPPEvaluation positive = fPositive == null ? - null : fPositive.computeForFunctionCall(parameterMap, context.recordStep()); - ICPPEvaluation negative = fNegative.computeForFunctionCall(parameterMap, context.recordStep()); - if (condition == fCondition && positive == fPositive && negative == fNegative) + null : fPositive.computeForFunctionCall(record, context.recordStep()); + ICPPEvaluation negative = fNegative.computeForFunctionCall(record, context.recordStep()); + if (condition == fCondition && positive == fPositive && negative == fNegative) { return this; - return new EvalConditional(condition, positive, negative, fPositiveThrows, fNegativeThrows, getTemplateDefinition()); + } + + EvalConditional evalConditional = new EvalConditional(condition, positive, negative, fPositiveThrows, fNegativeThrows, getTemplateDefinition()); + return evalConditional; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConstructor.java new file mode 100644 index 00000000000..8b3123ee0e7 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConstructor.java @@ -0,0 +1,339 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; + +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.cdt.core.dom.ast.ASTNodeFactoryFactory; +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; +import org.eclipse.cdt.core.dom.ast.IASTInitializer; +import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +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.ICPPTemplateArgument; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.internal.core.dom.parser.CompositeValue; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluationOwner; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class EvalConstructor extends CPPDependentEvaluation { + private final IType type; + private final ICPPConstructor constructor; + private final ICPPEvaluation[] arguments; + private boolean checkedIsTypeDependent; + private boolean isTypeDependent; + static private final IASTName tempName = ASTNodeFactoryFactory.getDefaultCPPNodeFactory().newName(); + + public EvalConstructor(IType type, ICPPConstructor constructor, ICPPEvaluation[] arguments, IBinding templateDefinition) { + super(templateDefinition); + this.type = type; + this.constructor = constructor; + this.arguments = arguments != null ? arguments : new ICPPEvaluation[0]; + } + + public EvalConstructor(IType type, ICPPConstructor constructor, ICPPEvaluation[] arguments, IASTNode pointOfDefinition) { + this(type, constructor, arguments, findEnclosingTemplate(pointOfDefinition)); + } + + @Override + public boolean isInitializerList() { + return false; + } + + @Override + public boolean isFunctionSet() { + return false; + } + + @Override + public boolean isTypeDependent() { + if (!checkedIsTypeDependent) { + checkedIsTypeDependent = true; + isTypeDependent = CPPTemplates.isDependentType(type) || containsDependentType(arguments); + } + return isTypeDependent; + } + + @Override + public boolean isValueDependent() { + if (CPPTemplates.isDependentType(type)) + return true; + for (ICPPEvaluation arg : arguments) { + if (arg.isValueDependent()) + return true; + } + return false; + } + + @Override + public boolean isConstantExpression(IASTNode point) { + return true; + } + + @Override + public IType getType(IASTNode point) { + return type; + } + + @Override + public IValue getValue(IASTNode point) { + // An EvalConstructor is never used to directly represent the evaluation of an expression. + // It only comes up while evaluating other evaluations. As such, its getValue() doesn't + // do anything; computeForFunctionCall() must be called on it to obtain a useful result. + return IntegralValue.ERROR; + } + + @Override + public ValueCategory getValueCategory(IASTNode point) { + return null; + } + + @Override + public ICPPEvaluation computeForFunctionCall(ActivationRecord callSiteRecord, ConstexprEvaluationContext context) { + final ICPPClassType classType = (ICPPClassType)SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); + final CompositeValue compositeValue = CompositeValue.create(classType); + ICPPEvaluation[] argList = evaluateArguments(arguments, callSiteRecord, context); + EvalFixed constructedObject = new EvalFixed(type, ValueCategory.PRVALUE, compositeValue); + CPPVariable binding = new CPPVariable(tempName); + + ActivationRecord localRecord = EvalFunctionCall.createActivationRecord( + this.constructor.getParameters(), argList, constructedObject, context.getPoint()); + localRecord.update(binding, constructedObject); + + ICPPExecution exec = constructor.getConstructorChainExecution(context.getPoint()); + if(exec instanceof ExecConstructorChain) { + ExecConstructorChain memberInitList = (ExecConstructorChain)exec; + Map ccInitializers = memberInitList.getConstructorChainInitializers(); + for(Entry ccInitializer : ccInitializers.entrySet()) { + if(ccInitializer.getKey() instanceof ICPPConstructor) { + ICPPClassType baseClassType = (ICPPClassType)ccInitializer.getKey().getOwner(); + final ICPPEvaluation memberEval = ccInitializer.getValue(); + ICPPEvaluation memberValue = memberEval.computeForFunctionCall(localRecord, context.recordStep()); + ICPPEvaluation[] baseClassValues = memberValue.getValue(context.getPoint()).getAllSubValues(); + + ICPPField[] baseFields = (ICPPField[])ClassTypeHelper.getFields(baseClassType, context.getPoint()); + for(ICPPField baseField : baseFields) { + // TODO: This has the same problem with multiple inheritance as + // CompositeValue.create(ICPPClassType). + int fieldPos = CPPASTFieldReference.getFieldPosition(baseField); + constructedObject.getValue(context.getPoint()).setSubValue(fieldPos, + baseClassValues[fieldPos]); + } + } + } + } + + + ICPPField[] fields = ClassTypeHelper.getDeclaredFields(classType, context.getPoint()); + for (ICPPField field : fields) { + final Entry ccInitializer = getInitializerFromMemberInitializerList(field, exec); + + ICPPEvaluation value = null; + if(ccInitializer != null) { + ExecDeclarator declaratorExec = getDeclaratorExecutionFromMemberInitializerList(ccInitializer); + value = getFieldValue(declaratorExec, classType, localRecord, context); + } else { + value = EvalUtil.getVariableValue(field, localRecord); + } + final int fieldPos = CPPASTFieldReference.getFieldPosition(field); + compositeValue.setSubValue(fieldPos, value); + } + + // TODO(nathanridge): EvalFunctionCall.computeForFunctionCall() will: + // - evaluate the arguments again + // - create another ActivationRecord (inside evaluateFunctionBody()) + // Are these necessary? + new EvalFunctionCall(argList, constructedObject, context.getPoint()).computeForFunctionCall( + localRecord, context.recordStep()); + ICPPEvaluation resultingObject = localRecord.getVariable(binding); + return resultingObject; + } + + private Entry getInitializerFromMemberInitializerList(ICPPField field, ICPPExecution exec) { + if(!(exec instanceof ExecConstructorChain)) { + return null; + } + + final ExecConstructorChain memberInitList = (ExecConstructorChain)exec; + for(Entry ccInitializer : memberInitList.getConstructorChainInitializers().entrySet()) { + final IBinding member = ccInitializer.getKey(); + if(member instanceof ICPPField && member.getName().equals(field.getName())) { + return ccInitializer; + } + } + return null; + } + + private ExecDeclarator getDeclaratorExecutionFromMemberInitializerList(Entry ccInitializer) { + final ICPPBinding member = (ICPPBinding)ccInitializer.getKey(); + final ICPPEvaluation memberEval = ccInitializer.getValue(); + return new ExecDeclarator(member, memberEval); + } + + private ICPPEvaluation getFieldValue(ExecDeclarator declaratorExec, ICPPClassType classType, ActivationRecord record, ConstexprEvaluationContext context) { + if(declaratorExec == null) { + return null; + } + + if(declaratorExec.executeForFunctionCall(record, context) != ExecIncomplete.INSTANCE) { + final ICPPEvaluation value = record.getVariable(declaratorExec.getDeclaredBinding()); + return value; + } + return null; + } + + public static ICPPEvaluation[] extractArguments(IASTInitializer initializer, ICPPConstructor constructor) { + ICPPEvaluation[] args = extractArguments(initializer); + if(args.length == 1 && constructor.getParameters().length > 1 && args[0] instanceof EvalInitList) { + EvalInitList evalInitList = (EvalInitList)args[0]; + args = evalInitList.getClauses(); + } + return args; + } + + public static ICPPEvaluation[] extractArguments(IASTInitializer initializer) { + if (initializer == null) { + return new ICPPEvaluation[0]; + } else if(initializer instanceof ICPPASTConstructorInitializer) { + ICPPASTConstructorInitializer ctorInitializer = (ICPPASTConstructorInitializer)initializer; + return evaluateArguments(ctorInitializer.getArguments()); + } else if(initializer instanceof ICPPASTInitializerList) { + ICPPASTInitializerList initList = (ICPPASTInitializerList)initializer; + return evaluateArguments(initList.getClauses()); + } else if(initializer instanceof IASTEqualsInitializer) { + IASTEqualsInitializer equalsInitalizer = (IASTEqualsInitializer)initializer; + IASTInitializerClause initClause = equalsInitalizer.getInitializerClause(); + return evaluateArguments(initClause); + } else { + throw new RuntimeException("this type of initializer is not supported"); //$NON-NLS-1$ + } + } + + private static ICPPEvaluation[] evaluateArguments(IASTInitializerClause... clauses) { + ICPPEvaluation[] args = new ICPPEvaluation[clauses.length]; + for (int i = 0; i < clauses.length; i++) { + ICPPEvaluationOwner clause = (ICPPEvaluationOwner)clauses[i]; + args[i] = clause.getEvaluation(); + } + return args; + } + + private ICPPEvaluation[] evaluateArguments(ICPPEvaluation[] arguments, ActivationRecord record, ConstexprEvaluationContext context) { + ICPPEvaluation[] argList = new ICPPEvaluation[arguments.length + 1]; + EvalBinding constructorBinding = new EvalBinding(constructor, constructor.getType(), getTemplateDefinition()); + argList[0] = constructorBinding; + for (int i = 0; i < arguments.length; i++) { + ICPPEvaluation evaluatedClause = arguments[i].computeForFunctionCall(record, context.recordStep()); + argList[i+1] = evaluatedClause; + } + return argList; + } + + + @Override + public int determinePackSize(ICPPTemplateParameterMap tpMap) { + int r = CPPTemplates.determinePackSize(type, tpMap); + for (ICPPEvaluation arg : arguments) { + r = CPPTemplates.combinePackSize(r, arg.determinePackSize(tpMap)); + } + return r; + } + + @Override + public boolean referencesTemplateParameter() { + for (ICPPEvaluation arg : arguments) { + if (arg.referencesTemplateParameter()) + return true; + } + return false; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EVAL_CONSTRUCTOR); + buffer.marshalType(type); + buffer.marshalBinding(constructor); + buffer.putInt(arguments.length); + for (ICPPEvaluation arg : arguments) { + buffer.marshalEvaluation(arg, includeValue); + } + marshalTemplateDefinition(buffer); + } + + public static ISerializableEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + IType type = buffer.unmarshalType(); + ICPPConstructor constructor = (ICPPConstructor)buffer.unmarshalBinding(); + int len = buffer.getInt(); + ICPPEvaluation[] arguments = new ICPPEvaluation[len]; + for (int i = 0; i < arguments.length; i++) { + arguments[i] = (ICPPEvaluation)buffer.unmarshalEvaluation(); + } + IBinding templateDefinition = buffer.unmarshalBinding(); + return new EvalConstructor(type, constructor, arguments, templateDefinition); + } + + @Override + public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { + IType newType = CPPTemplates.instantiateType(type, context); + + ICPPEvaluation[] newArguments = new ICPPEvaluation[arguments.length]; + for(int i = 0; i < arguments.length; i++) { + newArguments[i] = arguments[i].instantiate(context, maxDepth); + } + + ICPPConstructor newConstructor; + try { + newConstructor = (ICPPConstructor)CPPTemplates.instantiateBinding(constructor, context, maxDepth); + if(newConstructor instanceof CPPDeferredFunction) { + ICPPFunction[] candidates = ((CPPDeferredFunction) newConstructor).getCandidates(); + if (candidates != null) { + CPPFunctionSet functionSet = new CPPFunctionSet(candidates, new ICPPTemplateArgument[]{}, null); + EvalFunctionSet evalFunctionSet = new EvalFunctionSet(functionSet, false, false, newType, + context.getPoint()); + ICPPEvaluation resolved = evalFunctionSet.resolveFunction(newArguments, context.getPoint()); + if(resolved instanceof EvalBinding) { + EvalBinding evalBinding = (EvalBinding)resolved; + newConstructor = (ICPPConstructor)evalBinding.getBinding(); + } + } + } + } catch (DOMException e) { + newConstructor = constructor; + } + + return new EvalConstructor(newType, newConstructor, newArguments, getTemplateDefinition()); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java index 63c6690086c..cac9cecf54f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java @@ -24,8 +24,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; @@ -36,8 +36,10 @@ import org.eclipse.core.runtime.CoreException; */ public class EvalFixed extends CPPEvaluation { public static final ICPPEvaluation INCOMPLETE = - new EvalFixed(ProblemType.UNKNOWN_FOR_EXPRESSION, PRVALUE, Value.ERROR); + new EvalFixed(ProblemType.UNKNOWN_FOR_EXPRESSION, PRVALUE, IntegralValue.ERROR); + + private final IType fType; private final IValue fValue; private final ValueCategory fValueCategory; @@ -58,10 +60,10 @@ public class EvalFixed extends CPPEvaluation { } if (type instanceof CPPBasicType) { - Long num = value.numericalValue(); + Number num = value.numberValue(); if (num != null) { CPPBasicType t = (CPPBasicType) type.clone(); - t.setAssociatedNumericalValue(num); + t.setAssociatedNumericalValue(num.longValue()); type = t; } } @@ -105,7 +107,7 @@ public class EvalFixed extends CPPEvaluation { public boolean isValueDependent() { if (!fCheckedIsValueDependent) { fCheckedIsValueDependent= true; - fIsValueDependent= Value.isDependentValue(fValue); + fIsValueDependent= IntegralValue.isDependentValue(fValue); } return fIsValueDependent; } @@ -141,7 +143,7 @@ public class EvalFixed extends CPPEvaluation { @Override public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { - includeValue= includeValue && fValue != Value.UNKNOWN; + includeValue= includeValue && fValue != IntegralValue.UNKNOWN; short firstBytes = ITypeMarshalBuffer.EVAL_FIXED; if (includeValue) firstBytes |= ITypeMarshalBuffer.FLAG1; @@ -180,7 +182,7 @@ public class EvalFixed extends CPPEvaluation { } IType type= buffer.unmarshalType(); - value= readValue ? buffer.unmarshalValue() : Value.UNKNOWN; + value= readValue ? buffer.unmarshalValue() : IntegralValue.UNKNOWN; return new EvalFixed(type, cat, value); } @@ -192,24 +194,26 @@ public class EvalFixed extends CPPEvaluation { return this; // If an error occurred while instantiating the value (such as a substitution failure), // propagate that error. - if (value == Value.ERROR) + if (value == IntegralValue.ERROR) return EvalFixed.INCOMPLETE; // Resolve the parameter pack type to the underlying type if the instantiated value is not dependent. - if (type instanceof ICPPParameterPackType && value.numericalValue() != null) + if (type instanceof ICPPParameterPackType && value.numberValue() != null) type = ((ICPPParameterPackType) type).getType(); return new EvalFixed(type, fValueCategory, value); } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { ICPPEvaluation eval = fValue.getEvaluation(); - if (eval == null) + if (eval == null) { return this; - eval = eval.computeForFunctionCall(parameterMap, context.recordStep()); - if (eval == fValue.getEvaluation()) + } + eval = eval.computeForFunctionCall(record, context.recordStep()); + if (eval == fValue.getEvaluation()) { return this; - return new EvalFixed(fType, fValueCategory, Value.create(eval)); + } + EvalFixed evalFixed = new EvalFixed(fType, fValueCategory, IntegralValue.create(eval)); + return evalFixed; } @Override @@ -221,4 +225,9 @@ public class EvalFixed extends CPPEvaluation { public boolean referencesTemplateParameter() { return false; } + + @Override + public String toString() { + return fType.toString() + ": " + fValue.toString(); //$NON-NLS-1$ + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java index b9daf5ea65a..f24bcd23f19 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java @@ -27,16 +27,22 @@ import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IPointerType; 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.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.internal.core.dom.parser.CompositeValue; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics.LookupMode; @@ -44,23 +50,26 @@ import org.eclipse.core.runtime.CoreException; public class EvalFunctionCall extends CPPDependentEvaluation { private final ICPPEvaluation[] fArguments; - private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; + private ICPPFunction fOverload = CPPFunction.UNINITIALIZED_FUNCTION; private IType fType; private boolean fCheckedIsConstantExpression; private boolean fIsConstantExpression; - public EvalFunctionCall(ICPPEvaluation[] args, IASTNode pointOfDefinition) { - this(args, findEnclosingTemplate(pointOfDefinition)); - } + private final ICPPEvaluation fImplicitThis; - public EvalFunctionCall(ICPPEvaluation[] args, IBinding templateDefinition) { + public EvalFunctionCall(ICPPEvaluation[] args, ICPPEvaluation owner, IBinding templateDefinition) { super(templateDefinition); - fArguments= args; + fArguments = args; + fImplicitThis = owner; + } + + public EvalFunctionCall(ICPPEvaluation[] args, ICPPEvaluation owner, IASTNode pointOfDefinition) { + this(args, owner, findEnclosingTemplate(pointOfDefinition)); } /** - * Returns arguments of the function call. The first argument is the function name, the rest - * are arguments passed to the function. + * Returns arguments of the function call. The first argument is the function name, the rest are arguments + * passed to the function. */ public ICPPEvaluation[] getArguments() { return fArguments; @@ -101,7 +110,7 @@ public class EvalFunctionCall extends CPPDependentEvaluation { public ICPPFunction getOverload(IASTNode point) { if (fOverload == CPPFunction.UNINITIALIZED_FUNCTION) { - fOverload= computeOverload(point); + fOverload = computeOverload(point); } return fOverload; } @@ -116,12 +125,12 @@ public class EvalFunctionCall extends CPPDependentEvaluation { OverloadableOperator.PAREN, LookupMode.NO_GLOBALS); } return null; - } + } @Override public IType getType(IASTNode point) { if (fType == null) - fType= computeType(point); + fType = computeType(point); return fType; } @@ -143,28 +152,29 @@ public class EvalFunctionCall extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { - ICPPEvaluation eval = computeForFunctionCall(new ConstexprEvaluationContext(point)); + ICPPEvaluation eval = evaluateFunctionBody(new ConstexprEvaluationContext(point)); if (eval == this) { - return Value.create(eval); + return IntegralValue.create(eval); } - return eval.getValue(point); + IValue value = eval.getValue(point); + return value; } @Override public ValueCategory getValueCategory(IASTNode point) { ICPPFunction overload = getOverload(point); - if (overload != null) - return valueCategoryFromFunctionCall(overload); + if (overload != null) + return valueCategoryFromFunctionCall(overload); IType t= fArguments[0].getType(point); if (t instanceof IPointerType) { - t= SemanticUtil.getNestedType(((IPointerType) t).getType(), TDEF | REF | CVTYPE); + t = SemanticUtil.getNestedType(((IPointerType) t).getType(), TDEF | REF | CVTYPE); } if (t instanceof IFunctionType) { return valueCategoryFromReturnType(((IFunctionType) t).getReturnType()); } return ValueCategory.PRVALUE; - } + } @Override public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { @@ -173,17 +183,20 @@ public class EvalFunctionCall extends CPPDependentEvaluation { for (ICPPEvaluation arg : fArguments) { buffer.marshalEvaluation(arg, includeValue); } + buffer.marshalEvaluation(fImplicitThis, includeValue); marshalTemplateDefinition(buffer); } - public static ISerializableEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { - int len= buffer.getInt(); + public static ISerializableEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) + throws CoreException { + int len = buffer.getInt(); ICPPEvaluation[] args = new ICPPEvaluation[len]; for (int i = 0; i < args.length; i++) { - args[i]= (ICPPEvaluation) buffer.unmarshalEvaluation(); + args[i] = (ICPPEvaluation) buffer.unmarshalEvaluation(); } + ICPPEvaluation implicitThis = (ICPPEvaluation)buffer.unmarshalEvaluation(); IBinding templateDefinition = buffer.unmarshalBinding(); - return new EvalFunctionCall(args, templateDefinition); + return new EvalFunctionCall(args, implicitThis, templateDefinition); } @Override @@ -191,62 +204,84 @@ public class EvalFunctionCall extends CPPDependentEvaluation { ICPPEvaluation[] args = instantiateCommaSeparatedSubexpressions(fArguments, context, maxDepth); if (args == fArguments) return this; - + if (args[0] instanceof EvalFunctionSet && getOverload(context.getPoint()) == null) { // Resolve the function using the parameters of the function call. EvalFunctionSet functionSet = (EvalFunctionSet) args[0]; args[0] = functionSet.resolveFunction(Arrays.copyOfRange(args, 1, args.length), context.getPoint()); } - return new EvalFunctionCall(args, getTemplateDefinition()); + + ICPPEvaluation newImplicitThis = fImplicitThis != null ? fImplicitThis.instantiate(context, maxDepth) : null; + return new EvalFunctionCall(args, newImplicitThis, getTemplateDefinition()); } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { - if (context.getStepsPerformed() >= ConstexprEvaluationContext.MAX_CONSTEXPR_EVALUATION_STEPS) + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + if (context.getStepsPerformed() >= ConstexprEvaluationContext.MAX_CONSTEXPR_EVALUATION_STEPS) { return EvalFixed.INCOMPLETE; + } - ICPPEvaluation[] args = fArguments; + ICPPEvaluation[] args = new ICPPEvaluation[fArguments.length]; + System.arraycopy(fArguments, 0, args, 0, fArguments.length); + + ICPPFunction functionBinding = resolveFunctionBinding(context.getPoint()); + ICPPParameter[] parameters = functionBinding.getParameters(); for (int i = 0; i < fArguments.length; i++) { - ICPPEvaluation arg = fArguments[i].computeForFunctionCall(parameterMap, context); - if (arg != fArguments[i]) { - if (args == fArguments) { - args = new ICPPEvaluation[fArguments.length]; - System.arraycopy(fArguments, 0, args, 0, fArguments.length); + ICPPEvaluation arg = fArguments[i].computeForFunctionCall(record, context.recordStep()); + if (i != 0 && isReference(parameters[i-1]) && fArguments[i] instanceof EvalBinding) { + final EvalBinding evalBinding = (EvalBinding)fArguments[i]; + IBinding binding = evalBinding.getBinding(); + // If the binding being referenced isn't present in the activation record, + // we won't be able to evaluate the function call. + if (record.getVariable(binding) == null) { + return EvalFixed.INCOMPLETE; + } + arg = new EvalReference(record, binding, evalBinding.getTemplateDefinition()); + } else if(i != 0 && !isReference(parameters[i-1])) { + IValue copiedValue = arg.getValue(context.getPoint()).clone(); + arg = new EvalFixed(arg.getType(context.getPoint()), arg.getValueCategory(context.getPoint()), copiedValue); + } + args[i] = arg; + } + + ICPPEvaluation owner = null; + if(functionBinding instanceof ICPPMethod) { + if(fImplicitThis instanceof EvalBinding) { + IBinding ownerBinding = ((EvalBinding)fImplicitThis).getBinding(); + if(record.getVariable(ownerBinding) != null) { + owner = new EvalReference(record, ownerBinding, fImplicitThis.getTemplateDefinition()); + } else { + owner = fImplicitThis; } - args[i] = arg; + } else if(fImplicitThis != null) { + owner = fImplicitThis.computeForFunctionCall(record, context); + } else { + owner = record.getImplicitThis(); } } - EvalFunctionCall eval = this; - if (args != fArguments) - eval = new EvalFunctionCall(args, getTemplateDefinition()); - return eval.computeForFunctionCall(context); - } - private ICPPEvaluation computeForFunctionCall(ConstexprEvaluationContext context) { - if (isValueDependent()) + return new EvalFunctionCall(args, owner, getTemplateDefinition()).evaluateFunctionBody(context.recordStep()); + } + + private ICPPEvaluation evaluateFunctionBody(ConstexprEvaluationContext context) { + if (isValueDependent()) { return this; + } + // If the arguments are not all constant expressions, there is // no point trying to substitute them into the return expression. - if (!areAllConstantExpressions(fArguments, 1, fArguments.length, context.getPoint())) - return this; - ICPPFunction function = getOverload(context.getPoint()); - if (function == null) { - IBinding binding = null; - if (fArguments[0] instanceof EvalBinding) { - binding = ((EvalBinding) fArguments[0]).getBinding(); - } else if (fArguments[0] instanceof EvalMemberAccess) { - binding = ((EvalMemberAccess) fArguments[0]).getMember(); - } - if (binding instanceof ICPPFunction) - function = (ICPPFunction) binding; + if (!areAllConstantExpressions(fArguments, 1, fArguments.length, context.getPoint())) { + return EvalFixed.INCOMPLETE; } - if (function == null) + ICPPFunction function = resolveFunctionBinding(context.getPoint()); + if (function == null) { return this; + } - ICPPEvaluation eval = CPPFunction.getReturnExpression(function, context.getPoint()); - if (eval == null) { - if (!(function instanceof ICPPTemplateInstance) + ActivationRecord record = createActivationRecord(function.getParameters(), fArguments, fImplicitThis, context.getPoint()); + ICPPExecution bodyExec = CPPFunction.getFunctionBodyExecution(function, context.getPoint()); + if (bodyExec == null) { + if (!(function instanceof ICPPTemplateInstance) || ((ICPPTemplateInstance) function).isExplicitSpecialization()) { return EvalFixed.INCOMPLETE; } @@ -254,41 +289,116 @@ public class EvalFunctionCall extends CPPDependentEvaluation { IBinding specialized = functionInstance.getSpecializedBinding(); if (!(specialized instanceof ICPPFunction)) return this; - eval = CPPFunction.getReturnExpression((ICPPFunction) specialized, context.getPoint()); - if (eval == null) - return EvalFixed.INCOMPLETE; - InstantiationContext instantiationContext = - new InstantiationContext(functionInstance.getTemplateParameterMap(), context.getPoint()); - return eval.instantiate(instantiationContext, Value.MAX_RECURSION_DEPTH); + bodyExec = CPPFunction.getFunctionBodyExecution((ICPPFunction) specialized, context.getPoint()); + // TODO(nathanridge): Instead of instantiating the execution below in instantiateFunctionBody(), + // have getFunctionBodyExecution() return the instantiated execution already. } - CPPFunctionParameterMap parameterMap = buildParameterMap(function, context.getPoint()); - return eval.computeForFunctionCall(parameterMap, context.recordStep()); + if(bodyExec != null) { + bodyExec = bodyExec.executeForFunctionCall(record, context.recordStep()); + + // If the function exited via a return statement, bodyExec.executeForFunctionCall() will have + // just returned the ExecReturn, which needs to be executed separately. + if(bodyExec != null) { + bodyExec = bodyExec.executeForFunctionCall(record, context.recordStep()); + if(bodyExec instanceof ExecReturn) { + ExecReturn execReturn = (ExecReturn) bodyExec; + + ICPPEvaluation returnValueEval = execReturn.getReturnValueEvaluation(); + // TODO(nathanridge): ExecReturn.executeForFunctionCall() already calls + // computeForFunctionCall() on the return value evaluation. Why do we + // need to do it again, and only if it's an EvalBinding? + if(returnValueEval instanceof EvalBinding) { + returnValueEval = returnValueEval.computeForFunctionCall(record, context.recordStep()); + } + return returnValueEval; + } else if(bodyExec == ExecIncomplete.INSTANCE) { + return EvalFixed.INCOMPLETE; + } + } + } + return EvalFixed.INCOMPLETE; } - private CPPFunctionParameterMap buildParameterMap(ICPPFunction function, IASTNode point) { - ICPPParameter[] parameters = function.getParameters(); - CPPFunctionParameterMap map = new CPPFunctionParameterMap(parameters.length); + private ICPPFunction resolveFunctionBinding(IASTNode point) { + ICPPFunction function = getOverload(point); + if (function == null) { + ICPPEvaluation funcEval = fArguments[0]; + if (funcEval instanceof EvalFunctionSet) { + EvalFunctionSet funcEvalFunctionSet = (EvalFunctionSet)funcEval; + funcEval = funcEvalFunctionSet.resolveFunction(Arrays.copyOfRange(fArguments, 1, fArguments.length), point); + } + + IBinding binding = null; + if (funcEval instanceof EvalBinding) { + EvalBinding funcEvalBinding = (EvalBinding)funcEval; + binding = funcEvalBinding.getBinding(); + } else if (funcEval instanceof EvalMemberAccess) { + EvalMemberAccess funcEvalMemberAccess = (EvalMemberAccess)funcEval; + binding = funcEvalMemberAccess.getMember(); + } + + if (binding instanceof ICPPFunction) { + function = (ICPPFunction) binding; + } + } + return function; + } + + private boolean isReference(IBinding binding) { + return binding instanceof IVariable + && (((IVariable) binding).getType() instanceof ICPPReferenceType || ((IVariable) binding) + .getType() instanceof IPointerType); + } + + public static ActivationRecord createActivationRecord(ICPPParameter[] parameters, ICPPEvaluation[] arguments, ICPPEvaluation implicitThis, IASTNode point) { + ActivationRecord record = new ActivationRecord(parameters, implicitThis); + + // We start at arguments[1] because arguments[0] is the function's evaluation. int j = 1; - for (int i = 0; i < parameters.length; i++) { - ICPPParameter param = parameters[i]; - if (param.isParameterPack()) { + for(ICPPParameter param : parameters) { + if (param.isParameterPack() || isSpecializedParameterPack(param)) { // The parameter pack consumes all remaining arguments. - j = fArguments.length; + int paramPackLen = arguments.length - j; + ICPPEvaluation[] values = new ICPPEvaluation[paramPackLen]; + IType[] types = new IType[paramPackLen]; + for(int i = 0; i < paramPackLen; i++) { + ICPPEvaluation arg = arguments[j+i]; + values[i] = arg; + types[i] = arg.getType(null); + } + + IValue paramPackValue = new CompositeValue(null, values); + IType paramPackType = new ParameterPackType(types); + EvalFixed paramPack = new EvalFixed(paramPackType, ValueCategory.PRVALUE, paramPackValue); + record.update(param, paramPack); + break; } else { - if (j < fArguments.length) { - ICPPEvaluation argument = maybeApplyConversion(fArguments[j++], param.getType(), point); - map.put(i, argument); + if (j < arguments.length) { + ICPPEvaluation argument = maybeApplyConversion(arguments[j++], param.getType(), point); + record.update(param, argument); } else if (param.hasDefaultValue()) { IValue value = param.getDefaultValue(); ICPPEvaluation eval = value.getEvaluation(); if (eval == null) { eval = new EvalFixed(param.getType(), ValueCategory.PRVALUE, value); } - map.put(i, eval); + record.update(param, eval); } } } - return map; + return record; + } + + private static boolean isSpecializedParameterPack(ICPPParameter param) { + if(param instanceof ICPPSpecialization) { + ICPPSpecialization paramSpecialization = (ICPPSpecialization)param; + IBinding specializedBinding = paramSpecialization.getSpecializedBinding(); + if(specializedBinding instanceof ICPPParameter) { + ICPPParameter specializedParam = (ICPPParameter)specializedBinding; + return specializedParam.isParameterPack(); + } + } + return false; } @Override @@ -308,4 +418,30 @@ public class EvalFunctionCall extends CPPDependentEvaluation { } return false; } + + public static class ParameterPackType implements IType { + private final IType[] types; + + public ParameterPackType(IType[] types) { + this.types = types; + } + + public IType[] getTypes() { + return types; + } + + @Override + public boolean isSameType(IType type) { + return false; + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + } + return null; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java index 9ccb67ddc93..db745d6bde1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java @@ -33,7 +33,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; @@ -167,7 +167,7 @@ public class EvalFunctionSet extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } @Override @@ -281,8 +281,7 @@ public class EvalFunctionSet extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { return this; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java index c2410dbf4ed..582535bb506 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java @@ -52,7 +52,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; @@ -159,7 +159,7 @@ public class EvalID extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { // Name lookup is not needed here because it was already done in the "instantiate" method. - return Value.create(this); + return IntegralValue.create(this); } @Override @@ -250,7 +250,7 @@ public class EvalID extends CPPDependentEvaluation { ICPPEvaluation fieldOwner= null; IType fieldOwnerType= withinNonStaticMethod(expr); if (fieldOwnerType != null) { - fieldOwner= new EvalFixed(fieldOwnerType, ValueCategory.LVALUE, Value.UNKNOWN); + fieldOwner= new EvalFixed(fieldOwnerType, ValueCategory.LVALUE, IntegralValue.UNKNOWN); } return new EvalID(fieldOwner, owner, name.getSimpleID(), isAddressOf(expr), @@ -370,7 +370,7 @@ public class EvalID extends CPPDependentEvaluation { return this; if (nameOwner instanceof ICPPClassType) { - ICPPEvaluation eval = resolveName((ICPPClassType) nameOwner, templateArgs, null, context.getPoint()); + ICPPEvaluation eval = resolveName((ICPPClassType) nameOwner, null, templateArgs, null, context.getPoint()); if (eval != null) return eval; if (!CPPTemplates.isDependentType((ICPPClassType) nameOwner)) @@ -390,8 +390,7 @@ public class EvalID extends CPPDependentEvaluation { IType fieldOwnerClassTypeCV = SemanticUtil.getNestedType(fieldOwnerType, TDEF | REF); IType fieldOwnerClassType = SemanticUtil.getNestedType(fieldOwnerClassTypeCV, CVTYPE); if (fieldOwnerClassType instanceof ICPPClassType) { - ICPPEvaluation eval = resolveName((ICPPClassType) fieldOwnerClassType, templateArgs, - fieldOwnerClassTypeCV, context.getPoint()); + ICPPEvaluation eval = resolveName((ICPPClassType) fieldOwnerClassType, fieldOwner, templateArgs, fieldOwnerClassTypeCV, context.getPoint()); if (eval != null) return eval; } @@ -402,18 +401,19 @@ public class EvalID extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { - if (fFieldOwner == null) + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + if (fFieldOwner == null) { return this; - ICPPEvaluation fieldOwner = fFieldOwner.computeForFunctionCall(parameterMap, context.recordStep()); - if (fieldOwner == fFieldOwner) + } + ICPPEvaluation fieldOwner = fFieldOwner.computeForFunctionCall(record, context.recordStep()); + if (fieldOwner == fFieldOwner) { return this; - return new EvalID(fieldOwner, fNameOwner, fName, fAddressOf, fQualified, fIsPointerDeref, - fTemplateArgs, getTemplateDefinition()); + } + EvalID newEvalID = new EvalID(fieldOwner, fNameOwner, fName, fAddressOf, fQualified, fIsPointerDeref, fTemplateArgs, getTemplateDefinition()); + return newEvalID; } - private ICPPEvaluation resolveName(ICPPClassType nameOwner, ICPPTemplateArgument[] templateArgs, + private ICPPEvaluation resolveName(ICPPClassType nameOwner, ICPPEvaluation ownerEval, ICPPTemplateArgument[] templateArgs, IType impliedObjectType, IASTNode point) { LookupData data = new LookupData(fName, templateArgs, point); data.qualified = fQualified; @@ -427,20 +427,23 @@ public class EvalID extends CPPDependentEvaluation { if (binding instanceof ICPPFunction) { ICPPFunction[] functions = new ICPPFunction[bindings.length]; System.arraycopy(bindings, 0, functions, 0, bindings.length); - return new EvalFunctionSet(new CPPFunctionSet(functions, templateArgs, null), fQualified, + return new EvalFunctionSet(new CPPFunctionSet(functions, templateArgs, null), fQualified, fAddressOf, impliedObjectType, getTemplateDefinition()); } if (binding instanceof CPPFunctionSet) { - return new EvalFunctionSet((CPPFunctionSet) binding, fQualified, fAddressOf, + return new EvalFunctionSet((CPPFunctionSet) binding, fQualified, fAddressOf, impliedObjectType, getTemplateDefinition()); } if (binding instanceof IEnumerator) { return new EvalBinding(binding, null, getTemplateDefinition()); - } + } if (binding instanceof ICPPMember) { - return new EvalMemberAccess(nameOwner, ValueCategory.PRVALUE, binding, false, - getTemplateDefinition()); - } + if(ownerEval != null) { + return new EvalMemberAccess(nameOwner, ownerEval.getValueCategory(point), binding, ownerEval, false, point); + } else { + return new EvalMemberAccess(nameOwner, ValueCategory.PRVALUE, binding, false, getTemplateDefinition()); + } + } } return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java index 1909bb72154..4281f7a6abb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java @@ -19,9 +19,10 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.internal.core.dom.parser.CompositeValue; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.core.runtime.CoreException; @@ -87,9 +88,18 @@ public class EvalInitList extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { - if (isValueDependent()) - return Value.create(this); - return Value.UNKNOWN; // TODO(sprigogin): Is this correct? + if (isValueDependent()) { + return IntegralValue.create(this); + } + if (getClauses().length > 1) { + return CompositeValue.create(this); + } + else if (getClauses().length == 1) { + return IntegralValue.create(getClauses()[0]); + } else { + return IntegralValue.UNKNOWN; + } + } @Override @@ -126,11 +136,13 @@ public class EvalInitList extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { ICPPEvaluation[] clauses = fClauses; + if (fClauses.length == 1) { + return fClauses[0].computeForFunctionCall(record, context.recordStep()); + } for (int i = 0; i < fClauses.length; i++) { - ICPPEvaluation clause = fClauses[i].computeForFunctionCall(parameterMap, context.recordStep()); + ICPPEvaluation clause = fClauses[i].computeForFunctionCall(record, context.recordStep()); if (clause != fClauses[i]) { if (clauses == fClauses) { clauses = new ICPPEvaluation[fClauses.length]; @@ -139,9 +151,8 @@ public class EvalInitList extends CPPDependentEvaluation { clauses[i] = clause; } } - if (clauses == fClauses) - return this; - return new EvalInitList(clauses, getTemplateDefinition()); + EvalInitList evalInit = new EvalInitList(clauses, this.getTemplateDefinition()); + return evalInit; } @Override @@ -161,4 +172,4 @@ public class EvalInitList extends CPPDependentEvaluation { } return false; } -} \ No newline at end of file +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java index 3cfa78deeb1..da95de5dd06 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java @@ -28,6 +28,7 @@ import java.util.Collection; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; +import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IFunction; @@ -40,12 +41,15 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; 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.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.internal.core.dom.parser.CompositeValue; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalUnknownScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; @@ -59,6 +63,12 @@ public class EvalMemberAccess extends CPPDependentEvaluation { private final IBinding fMember; private final ValueCategory fOwnerValueCategory; private final boolean fIsPointerDeref; + + // An EvalMemberAccess has an owner evaluation if it does not represent + // a member access through the "this" pointer. If it does, the owner + // evaluation is derived from the activation record (passed to + // computeForFunctionCall()). + private ICPPEvaluation fOwnerEval; private IType fType; private boolean fIsTypeDependent; @@ -73,11 +83,22 @@ public class EvalMemberAccess extends CPPDependentEvaluation { public EvalMemberAccess(IType ownerType, ValueCategory ownerValueCat, IBinding member, boolean isPointerDeref, IBinding templateDefinition) { + this(ownerType, ownerValueCat, member, null, isPointerDeref, templateDefinition); + } + + public EvalMemberAccess(IType ownerType, ValueCategory ownerValueCat, IBinding member, + ICPPEvaluation ownerEval, boolean isDeref, IASTNode pointOfDefinition) { + this(ownerType, ownerValueCat, member, ownerEval, isDeref, findEnclosingTemplate(pointOfDefinition)); + } + + public EvalMemberAccess(IType ownerType, ValueCategory ownerValueCat, IBinding member, + ICPPEvaluation ownerEval, boolean isDeref, IBinding templateDefinition) { super(templateDefinition); - fOwnerType= ownerType; - fOwnerValueCategory= ownerValueCat; - fMember= member; - fIsPointerDeref= isPointerDeref; + fOwnerType = ownerType; + fOwnerValueCategory = ownerValueCat; + fMember = member; + fIsPointerDeref = isDeref; + fOwnerEval = ownerEval; } public IType getOwnerType() { @@ -87,6 +108,10 @@ public class EvalMemberAccess extends CPPDependentEvaluation { public ValueCategory getOwnerValueCategory() { return fOwnerValueCategory; } + + public ICPPEvaluation getOwnerEval() { + return fOwnerEval; + } public IBinding getMember() { return fMember; @@ -109,8 +134,8 @@ public class EvalMemberAccess extends CPPDependentEvaluation { @Override public boolean isTypeDependent() { if (!fCheckedIsTypeDependent) { - fCheckedIsTypeDependent= true; - fIsTypeDependent= computeIsTypeDependent(); + fCheckedIsTypeDependent = true; + fIsTypeDependent = computeIsTypeDependent(); } return fIsTypeDependent; } @@ -120,11 +145,11 @@ public class EvalMemberAccess extends CPPDependentEvaluation { if (fMember instanceof ICPPUnknownBinding) { return true; } else if (fMember instanceof IEnumerator) { - t= ((IEnumerator) fMember).getType(); + t = ((IEnumerator) fMember).getType(); } else if (fMember instanceof IVariable) { t = ((IVariable) fMember).getType(); } else if (fMember instanceof IFunction) { - t= ((IFunction) fMember).getType(); + t = ((IFunction) fMember).getType(); } else { return false; } @@ -134,21 +159,21 @@ public class EvalMemberAccess extends CPPDependentEvaluation { @Override public boolean isValueDependent() { if (!fCheckedIsValueDependent) { - fCheckedIsValueDependent= true; - fIsValueDependent= computeIsValueDependent(); + fCheckedIsValueDependent = true; + fIsValueDependent = computeIsValueDependent(); } return fIsValueDependent; } - + private boolean computeIsValueDependent() { if (fMember instanceof ICPPUnknownBinding) { return true; } if (fMember instanceof IEnumerator) { - return Value.isDependentValue(((IEnumerator) fMember).getValue()); + return IntegralValue.isDependentValue(((IEnumerator) fMember).getValue()); } if (fMember instanceof IVariable) { - return Value.isDependentValue(((IVariable) fMember).getInitialValue()); + return IntegralValue.isDependentValue(((IVariable) fMember).getInitialValue()); } if (fMember instanceof IFunction) { return false; @@ -158,10 +183,9 @@ public class EvalMemberAccess extends CPPDependentEvaluation { @Override public boolean isConstantExpression(IASTNode point) { - // TODO(nathanridge): - // This could be a constant expression if the field owner - // is a constant expression, but we don't have access to - // the field owner's evaluation, only its type. + if (fOwnerEval != null) { + return fOwnerEval.isConstantExpression(point); + } return false; } @@ -190,29 +214,29 @@ public class EvalMemberAccess extends CPPDependentEvaluation { * examine for type information. */ - ICPPEvaluation[] args= { new EvalFixed(type, LVALUE, Value.UNKNOWN) }; + ICPPEvaluation[] args= { new EvalFixed(type, LVALUE, IntegralValue.UNKNOWN) }; ICPPFunction op= CPPSemantics.findOverloadedOperator(point, null, args, classType, OverloadableOperator.ARROW, LookupMode.NO_GLOBALS); - if (op == null) - break; + if (op == null) + break; - if (functionBindings != null) - functionBindings.add(op); + if (functionBindings != null) + functionBindings.add(op); - type= typeFromFunctionCall(op); - type= SemanticUtil.mapToAST(type, point); - } + type = typeFromFunctionCall(op); + type = SemanticUtil.mapToAST(type, point); + } - IType prValue= prvalueTypeWithResolvedTypedefs(type); + IType prValue = prvalueTypeWithResolvedTypedefs(type); if (prValue instanceof IPointerType) { return glvalueType(((IPointerType) prValue).getType()); } if (CPPTemplates.isDependentType(type)) { - return returnDependent - // The type resulting from dereferencing 'type' - ? new TypeOfDependentExpression(new EvalUnary(IASTUnaryExpression.op_star, - new EvalFixed(type, LVALUE, Value.UNKNOWN), null, point)) + return returnDependent + // The type resulting from dereferecing 'type' + ? new TypeOfDependentExpression(new EvalUnary(IASTUnaryExpression.op_star, + new EvalFixed(type, LVALUE, IntegralValue.UNKNOWN), null, point)) : null; } @@ -222,7 +246,7 @@ public class EvalMemberAccess extends CPPDependentEvaluation { @Override public IType getType(IASTNode point) { if (fType == null) { - fType= computeType(point); + fType = computeType(point); } return fType; } @@ -236,18 +260,18 @@ public class EvalMemberAccess extends CPPDependentEvaluation { } if (fMember instanceof IVariable) { IType e2 = ((IVariable) fMember).getType(); - e2= SemanticUtil.getNestedType(e2, TDEF); + e2 = SemanticUtil.getNestedType(e2, TDEF); if (e2 instanceof ICPPReferenceType) { - e2= glvalueType(e2); + e2 = glvalueType(e2); } else if (fMember instanceof ICPPField && !((ICPPField) fMember).isStatic()) { e2 = addQualifiersForAccess((ICPPField) fMember, e2, fOwnerType); if (!fIsPointerDeref && fOwnerValueCategory == PRVALUE) { - e2= prvalueType(e2); + e2 = prvalueType(e2); } else { - e2= glvalueType(e2); + e2 = glvalueType(e2); } } - return SemanticUtil.mapToAST(e2, point); + return SemanticUtil.mapToAST(e2, point); } if (fMember instanceof IFunction) { return SemanticUtil.mapToAST(((IFunction) fMember).getType(), point); @@ -261,35 +285,47 @@ public class EvalMemberAccess extends CPPDependentEvaluation { if (field.isMutable()) { // Remove const, add union of volatile. if (cvq2.isConst()) { - fieldType= SemanticUtil.getNestedType(fieldType, ALLCVQ | TDEF | REF); + fieldType = SemanticUtil.getNestedType(fieldType, ALLCVQ | TDEF | REF); } - fieldType= SemanticUtil.addQualifiers(fieldType, false, cvq1.isVolatile() || cvq2.isVolatile(), cvq2.isRestrict()); + fieldType = SemanticUtil.addQualifiers(fieldType, false, cvq1.isVolatile() || cvq2.isVolatile(), + cvq2.isRestrict()); } else { - fieldType= SemanticUtil.addQualifiers(fieldType, cvq1.isConst(), cvq1.isVolatile(), cvq2.isRestrict()); + fieldType = SemanticUtil.addQualifiers(fieldType, cvq1.isConst(), cvq1.isVolatile(), + cvq2.isRestrict()); } return fieldType; } @Override public IValue getValue(IASTNode point) { + if (fOwnerEval != null) { + int fieldPos = CPPASTFieldReference.getFieldPosition(fMember, fOwnerType); + CompositeValue compValue = (CompositeValue) fOwnerEval.getValue(point); + ICPPEvaluation field = compValue.getSubValue(fieldPos); + if(field != null) { + return field.getValue(point); + } else { + return IntegralValue.UNKNOWN; + } + } if (fMember instanceof IEnumerator) { return ((IEnumerator) fMember).getValue(); } if (fMember instanceof IVariable) { IValue initialValue = ((IVariable) fMember).getInitialValue(); - return initialValue == null ? Value.UNKNOWN : initialValue; + return initialValue == null ? IntegralValue.UNKNOWN : initialValue; } if (fMember instanceof IFunction) { - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } - return Value.create(this); + return IntegralValue.create(this); } @Override public ValueCategory getValueCategory(IASTNode point) { if (fMember instanceof IVariable) { - IType e2= ((IVariable) fMember).getType(); - e2= SemanticUtil.getNestedType(e2, TDEF); + IType e2 = ((IVariable) fMember).getType(); + e2 = SemanticUtil.getNestedType(e2, TDEF); if (e2 instanceof ICPPReferenceType) { return LVALUE; } @@ -321,30 +357,33 @@ public class EvalMemberAccess extends CPPDependentEvaluation { buffer.putShort(firstBytes); buffer.marshalType(fOwnerType); buffer.marshalBinding(fMember); + buffer.marshalEvaluation(fOwnerEval, includeValue); marshalTemplateDefinition(buffer); } - public static ISerializableEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { - boolean isDeref= (firstBytes & ITypeMarshalBuffer.FLAG1) != 0; + public static ISerializableEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) + throws CoreException { + boolean isDeref = (firstBytes & ITypeMarshalBuffer.FLAG1) != 0; ValueCategory ownerValueCat; if ((firstBytes & ITypeMarshalBuffer.FLAG2) != 0) { - ownerValueCat= LVALUE; + ownerValueCat = LVALUE; } else if ((firstBytes & ITypeMarshalBuffer.FLAG3) != 0) { - ownerValueCat= XVALUE; + ownerValueCat = XVALUE; } else { - ownerValueCat= PRVALUE; + ownerValueCat = PRVALUE; } - IType ownerType= buffer.unmarshalType(); - IBinding member= buffer.unmarshalBinding(); - IBinding templateDefinition= buffer.unmarshalBinding(); - return new EvalMemberAccess(ownerType, ownerValueCat, member, isDeref, templateDefinition); + IType ownerType = buffer.unmarshalType(); + IBinding member = buffer.unmarshalBinding(); + ICPPEvaluation ownerEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + IBinding templateDefinition = buffer.unmarshalBinding(); + return new EvalMemberAccess(ownerType, ownerValueCat, member, ownerEval, isDeref, templateDefinition); } @Override public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { IType ownerType = CPPTemplates.instantiateType(fOwnerType, context); - if (ownerType == fOwnerType) + if (ownerType == fOwnerType && fOwnerEval == null) return this; IBinding member = fMember; @@ -352,13 +391,65 @@ public class EvalMemberAccess extends CPPDependentEvaluation { if (ownerClass instanceof ICPPClassSpecialization) { member = CPPTemplates.createSpecialization((ICPPClassSpecialization) ownerClass, fMember, context.getPoint()); } - return new EvalMemberAccess(ownerType, fOwnerValueCategory, member, fIsPointerDeref, getTemplateDefinition()); + ICPPEvaluation ownerEval = fOwnerEval; + if (ownerEval != null) { + ownerEval = ownerEval.instantiate(context, maxDepth); + if (ownerType == fOwnerType && ownerEval == fOwnerEval) + return this; + } + return new EvalMemberAccess(ownerType, fOwnerValueCategory, member, ownerEval, fIsPointerDeref, + getTemplateDefinition()); + } + + + private boolean isMemberAccessThroughThisPointer() { + if(fOwnerEval == null) { + return true; + } else if(fOwnerEval instanceof EvalFixed) { + EvalFixed evalFixed = (EvalFixed)fOwnerEval; + return evalFixed.getValue() == IntegralValue.THIS; + } + return false; + } + + private ICPPEvaluation getOwnerEval(ActivationRecord record) { + if(isMemberAccessThroughThisPointer()) { + return record.getImplicitThis(); + } + return fOwnerEval; } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { - return this; + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + final ICPPEvaluation ownerEval = getOwnerEval(record); + if (fMember instanceof ICPPMethod) { + EvalBinding evalBinding = new EvalBinding(fMember, fType, getTemplateDefinition()); + return evalBinding; + } + if(ownerEval == null) { + return this; + } + + int fieldPos = CPPASTFieldReference.getFieldPosition(fMember, fOwnerType); + ICPPEvaluation evaluatedOwner = ownerEval.computeForFunctionCall(record, context); + if (evaluatedOwner instanceof EvalPointer) { + evaluatedOwner = ((EvalPointer) evaluatedOwner).dereference(); + } + + if(fMember instanceof ICPPField) { + ICPPField field = (ICPPField) fMember; + if(field.getType() instanceof IArrayType) { + EvalPointer evalPointer = new EvalPointer(record, + new EvalCompositeAccess(new EvalCompositeAccess(evaluatedOwner, fieldPos), 0), + getTemplateDefinition()); + return evalPointer; + } + } + + EvalReference evalRef = new EvalReference(record, + new EvalCompositeAccess(evaluatedOwner, fieldPos), + getTemplateDefinition()); + return evalRef; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalParameterPack.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalParameterPack.java index e1ef75f1450..e6d16170fa7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalParameterPack.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalParameterPack.java @@ -18,8 +18,8 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterPackType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; @@ -85,7 +85,7 @@ public class EvalParameterPack extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { - return Value.create(fExpansionPattern); + return IntegralValue.create(fExpansionPattern); } @Override @@ -102,13 +102,14 @@ public class EvalParameterPack extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { - ICPPEvaluation expansionPattern = fExpansionPattern.computeForFunctionCall(parameterMap, - context.recordStep()); - if (expansionPattern == fExpansionPattern) + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPEvaluation expansionPattern = fExpansionPattern.computeForFunctionCall(record, context.recordStep()); + if (expansionPattern == fExpansionPattern) { return this; - return new EvalParameterPack(expansionPattern, getTemplateDefinition()); + } + + EvalParameterPack evalParamPack = new EvalParameterPack(expansionPattern, getTemplateDefinition()); + return evalParamPack; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalPointer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalPointer.java new file mode 100644 index 00000000000..a84ce15cfeb --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalPointer.java @@ -0,0 +1,146 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.core.runtime.CoreException; + +public class EvalPointer extends EvalReference { + // The position will only be nonzero if the EvalReference has a referredSubValue, + // not a referredBinding. + private int position; + + public EvalPointer(ActivationRecord record, EvalCompositeAccess referredSubValue, IASTNode point) { + this(record, referredSubValue, findEnclosingTemplate(point)); + } + + public EvalPointer(ActivationRecord record, EvalCompositeAccess referredSubValue, IBinding templateDefinition) { + this(record, referredSubValue, templateDefinition, referredSubValue.getElementId()); + } + + public EvalPointer(ActivationRecord record, EvalCompositeAccess referredSubValue, IBinding templateDefinition, int offset) { + super(record, referredSubValue, templateDefinition); + setPosition(offset); + } + + public EvalPointer(ActivationRecord record, IBinding referredBinding, IBinding templateDefinition) { + super(record, referredBinding, templateDefinition); + setPosition(0); + } + + public EvalReference dereference() { + if (referredSubValue != null) { + final EvalCompositeAccess pointedToValue = new EvalCompositeAccess(referredSubValue.getParent(), getPosition()); + return new EvalReference(owningRecord, pointedToValue, getTemplateDefinition()); + } else { + return new EvalReference(owningRecord,referredBinding, getTemplateDefinition()); + } + } + + @Override + public IType getType(IASTNode point) { + IType valueType = getTargetEvaluation().getType(point); + return new CPPPointerType(valueType, false, false, false); + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + invalidatePointerIfPositionOutOfRange(); + } + + private void invalidatePointerIfPositionOutOfRange() { + if (isPositionOutOfRange()) { + referredSubValue = new EvalCompositeAccess(EvalFixed.INCOMPLETE, 0); + referredBinding = null; + } + } + + private boolean isPositionOutOfRange() { + return subValuePositionOutOfrange() || (this.referredBinding != null && position != 0); + } + + private boolean subValuePositionOutOfrange() { + return referredSubValue != null && (position - referredSubValue.getParent().getValue(null).numberOfSubValues() > 0 || position < 0); + } + + @Override + public IValue getValue(IASTNode point) { + // TODO(nathanridge): Why does it make sense to consider a pointer's value to be its offset + // into the underlying array? + return IntegralValue.create(position); + } + + @Override + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + return this; + } + + public EvalPointer copy() { + if (referredSubValue != null) { + return new EvalPointer(owningRecord, referredSubValue, getTemplateDefinition(), position); + } else { + return new EvalPointer(owningRecord, referredBinding, getTemplateDefinition()); + } + } + + public static EvalPointer createFromAddress(EvalReference reference) { + if (reference.referredSubValue != null) { + return new EvalPointer(reference.owningRecord, reference.referredSubValue, reference.getTemplateDefinition()); + } else { + return new EvalPointer(reference.owningRecord, reference.referredBinding, reference.getTemplateDefinition()); + } + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + short firstBytes = ITypeMarshalBuffer.EVAL_POINTER; + if (referredSubValue != null) { + firstBytes |= ITypeMarshalBuffer.FLAG1; + } + buffer.putShort(firstBytes); + if (referredSubValue != null) { + buffer.marshalEvaluation(referredSubValue, includeValue); + buffer.putInt(position); + } else { + buffer.marshalBinding(referredBinding); + buffer.marshalEvaluation(owningRecord.getVariable(referredBinding), includeValue); + } + marshalTemplateDefinition(buffer); + } + + public static ISerializableEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + boolean subValue = (firstBytes & ITypeMarshalBuffer.FLAG1) != 0; + if (subValue) { + EvalCompositeAccess referredSubValue = (EvalCompositeAccess) buffer.unmarshalEvaluation(); + int position = buffer.getInt(); + IBinding templateDefinition = buffer.unmarshalBinding(); + return new EvalPointer(new ActivationRecord(), referredSubValue, templateDefinition, position); + } else { + IBinding referredBinding = buffer.unmarshalBinding(); + ICPPEvaluation value = (ICPPEvaluation) buffer.unmarshalEvaluation(); + ActivationRecord record = new ActivationRecord(); + record.update(referredBinding, value); + IBinding templateDefinition = buffer.unmarshalBinding(); + return new EvalPointer(record, referredBinding, templateDefinition); + } + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalReference.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalReference.java new file mode 100644 index 00000000000..ff51f3d8c3b --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalReference.java @@ -0,0 +1,176 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class EvalReference extends CPPDependentEvaluation { + protected final ActivationRecord owningRecord; + + // The following invariant must be true for instances of this class: + // (referredBinding == null) != (referredSubValue == null) + protected IBinding referredBinding; + protected EvalCompositeAccess referredSubValue; + + EvalReference(ActivationRecord owningRecord, IBinding referredBinding, IBinding templateDefinition) { + super(templateDefinition); + this.owningRecord = owningRecord; + this.referredBinding = referredBinding; + } + + EvalReference(ActivationRecord owningRecord, IBinding referredBinding, IASTNode point) { + this(owningRecord, referredBinding, findEnclosingTemplate(point)); + } + + EvalReference(ActivationRecord owningRecord, EvalCompositeAccess referredSubValue, IBinding templateDefinition) { + super(templateDefinition); + this.owningRecord = owningRecord; + this.referredSubValue = referredSubValue; + this.referredBinding = null; + } + + EvalReference(ActivationRecord owningRecord, EvalCompositeAccess referredSubValue, IASTNode point) { + this(owningRecord, referredSubValue, findEnclosingTemplate(point)); + } + + @Override + public boolean isInitializerList() { + return getTargetEvaluation().isInitializerList(); + } + + @Override + public boolean isFunctionSet() { + return getTargetEvaluation().isFunctionSet(); + } + + @Override + public boolean isTypeDependent() { + return getTargetEvaluation().isTypeDependent(); + } + + @Override + public boolean isValueDependent() { + return getTargetEvaluation().isValueDependent(); + } + + @Override + public boolean isConstantExpression(IASTNode point) { + return getTargetEvaluation().isConstantExpression(point); + } + + @Override + public IType getType(IASTNode point) { + return getTargetEvaluation().getType(point); + } + + @Override + public IValue getValue(IASTNode point) { + return getTargetEvaluation().getValue(null); + } + + public ICPPEvaluation getTargetEvaluation() { + if (referredSubValue != null) { + return referredSubValue; + } + return owningRecord.getVariable(referredBinding); + } + + public void update(ICPPEvaluation eval) { + if (referredBinding != null) { + ICPPEvaluation oldValue = owningRecord.getVariable(referredBinding); + if (oldValue instanceof EvalReference) { + ((EvalReference) oldValue).update(eval); + } else { + owningRecord.update(referredBinding, eval); + } + } else { + referredSubValue.update(eval); + } + } + + public IBinding getReferredBinding() { + return referredBinding; + } + + @Override + public ValueCategory getValueCategory(IASTNode point) { + return getTargetEvaluation().getValueCategory(point); + } + + @Override + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + if (referredSubValue != null) { + return referredSubValue.computeForFunctionCall(record, context); + } + ICPPEvaluation referredEval = owningRecord.getVariable(referredBinding); + if (referredEval instanceof EvalReference) { + // TODO(nathanridge): Why are we doing this for EvalReference only? + return referredEval.computeForFunctionCall(record, context); + } + return referredEval; + } + + @Override + public int determinePackSize(ICPPTemplateParameterMap tpMap) { + return getTargetEvaluation().determinePackSize(tpMap); + } + + @Override + public boolean referencesTemplateParameter() { + return getTargetEvaluation().referencesTemplateParameter(); + } + + @Override + public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { + // TODO(nathanridge): Why are we losing the EvalReference wrapper here? + return getTargetEvaluation().instantiate(context, maxDepth); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + short firstBytes = ITypeMarshalBuffer.EVAL_REFERENCE; + if (referredSubValue != null) { + firstBytes |= ITypeMarshalBuffer.FLAG1; + } + buffer.putShort(firstBytes); + if (referredSubValue != null) { + buffer.marshalEvaluation(referredSubValue, includeValue); + } else { + buffer.marshalBinding(referredBinding); + buffer.marshalEvaluation(owningRecord.getVariable(referredBinding), includeValue); + } + marshalTemplateDefinition(buffer); + } + + public static ISerializableEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + boolean subValue = (firstBytes & ITypeMarshalBuffer.FLAG1) != 0; + if (subValue) { + EvalCompositeAccess referredSubValue = (EvalCompositeAccess) buffer.unmarshalEvaluation(); + IBinding templateDefinition = buffer.unmarshalBinding(); + return new EvalReference(new ActivationRecord(), referredSubValue, templateDefinition); + } else { + IBinding referredBinding = buffer.unmarshalBinding(); + ICPPEvaluation value = (ICPPEvaluation) buffer.unmarshalEvaluation(); + ActivationRecord record = new ActivationRecord(); + record.update(referredBinding, value); + IBinding templateDefinition = buffer.unmarshalBinding(); + return new EvalReference(record, referredBinding, templateDefinition); + } + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java index 621a91b1d7a..ff846f37936 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java @@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding; 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.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; @@ -29,10 +30,11 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.internal.core.dom.parser.CompositeValue; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; @@ -45,9 +47,17 @@ import org.eclipse.core.runtime.CoreException; * Performs evaluation of an expression. */ public class EvalTypeId extends CPPDependentEvaluation { + public static final ICPPFunction AGGREGATE_INITIALIZATION = new CPPFunction(null) { + @Override + public String toString() { + return "AGGREGATE_INITIALIZATION"; //$NON-NLS-1$ + } + }; + private final IType fInputType; private final ICPPEvaluation[] fArguments; private final boolean fRepresentsNewExpression; + private boolean fUsesBracedInitList; // Whether the constructor call uses { ... } instead of ( ... ). private IType fOutputType; private ICPPFunction fConstructor = CPPFunction.UNINITIALIZED_FUNCTION; @@ -56,15 +66,13 @@ public class EvalTypeId extends CPPDependentEvaluation { private boolean fCheckedIsConstantExpression; private boolean fIsConstantExpression; - public EvalTypeId(IType type, IASTNode pointOfDefinition, ICPPEvaluation... arguments) { - this(type, findEnclosingTemplate(pointOfDefinition), false, arguments); + public EvalTypeId(IType type, IASTNode pointOfDefinition, boolean usesBracedInitList, + ICPPEvaluation... arguments) { + this(type, findEnclosingTemplate(pointOfDefinition), false, usesBracedInitList, arguments); } - public EvalTypeId(IType type, IBinding templateDefinition, ICPPEvaluation... arguments) { - this(type, templateDefinition, false, arguments); - } - - private EvalTypeId(IType type, IBinding templateDefinition, boolean forNewExpression, ICPPEvaluation... arguments) { + public EvalTypeId(IType type, IBinding templateDefinition, boolean forNewExpression, + boolean usesBracedInitList, ICPPEvaluation... arguments) { super(templateDefinition); if (arguments == null) throw new NullPointerException("arguments"); //$NON-NLS-1$ @@ -72,12 +80,15 @@ public class EvalTypeId extends CPPDependentEvaluation { fInputType= type; fArguments= arguments; fRepresentsNewExpression = forNewExpression; + fUsesBracedInitList = usesBracedInitList; } - public static EvalTypeId createForNewExpression(IType type, IASTNode pointOfDefinition, ICPPEvaluation... arguments) { - return new EvalTypeId(type, findEnclosingTemplate(pointOfDefinition), true, arguments); + public static EvalTypeId createForNewExpression(IType type, IASTNode pointOfDefinition, + boolean usesBracedInitList, ICPPEvaluation... arguments) { + return new EvalTypeId(type, findEnclosingTemplate(pointOfDefinition), true, usesBracedInitList, + arguments); } - + public IType getInputType() { return fInputType; } @@ -85,6 +96,14 @@ public class EvalTypeId extends CPPDependentEvaluation { public ICPPEvaluation[] getArguments() { return fArguments; } + + public boolean representsNewExpression() { + return fRepresentsNewExpression; + } + + public boolean usesBracedInitList() { + return fUsesBracedInitList; + } @Override public boolean isInitializerList() { @@ -117,18 +136,60 @@ public class EvalTypeId extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { if (isValueDependent()) - return Value.create(this); + return IntegralValue.create(this); if (isTypeDependent()) - return Value.create(this); + return IntegralValue.create(this); if (fRepresentsNewExpression) - return Value.UNKNOWN; - if (fOutputType instanceof ICPPClassType) { - // TODO(sprigogin): Simulate execution of a ctor call. - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; + + if (fInputType instanceof ICPPClassType) { + ICPPClassType classType = (ICPPClassType)fInputType; + IBinding ctor = getConstructor(null); + if(EvalUtil.isCompilerGeneratedCtor(ctor)) { + return CompositeValue.create(classType); + } else if (ctor == AGGREGATE_INITIALIZATION) { + // TODO(nathanridge): Support aggregate initialization. + return IntegralValue.UNKNOWN; + } else if (ctor != null) { + EvalConstructor evalCtor = new EvalConstructor(classType, (ICPPConstructor)ctor, + fArguments, getTemplateDefinition()); + ICPPEvaluation computedEvalCtor = evalCtor.computeForFunctionCall(new ActivationRecord(), new ConstexprEvaluationContext(point)); + return computedEvalCtor.getValue(point); + } else { + return IntegralValue.ERROR; + } } - if (fArguments.length == 1) + if (fArguments.length == 0 || isEmptyInitializerList(fArguments)) { + if (fInputType instanceof ICPPBasicType) { + switch(((ICPPBasicType) fInputType).getKind()) { + case eInt: + case eInt128: + case eDouble: + case eBoolean: + case eFloat: + case eFloat128: + case eNullPtr: + case eChar: + case eChar16: + case eChar32: + case eWChar: + return IntegralValue.create(0l); + case eUnspecified: + case eVoid: + default: + return IntegralValue.UNKNOWN; + } + + } + } + if (fArguments.length == 1) { return fArguments[0].getValue(point); - return Value.UNKNOWN; + } + return IntegralValue.UNKNOWN; + } + + private boolean isEmptyInitializerList(ICPPEvaluation[] arguments) { + return arguments.length == 1 && arguments[0] instanceof EvalInitList && ((EvalInitList) arguments[0]).getClauses().length == 0; } @Override @@ -178,6 +239,14 @@ public class EvalTypeId extends CPPDependentEvaluation { return fConstructor; } + private static boolean allConstructorsAreCompilerGenerated(ICPPConstructor[] constructors) { + for (ICPPConstructor constructor : constructors) { + if (!EvalUtil.isCompilerGeneratedCtor(constructor)) + return false; + } + return true; + } + private ICPPFunction computeConstructor(IASTNode point) { if (isTypeDependent()) return null; @@ -217,6 +286,10 @@ public class EvalTypeId extends CPPDependentEvaluation { } catch (DOMException e) { CCorePlugin.log(e); } + + if (fUsesBracedInitList && allConstructorsAreCompilerGenerated(constructors)) { + return AGGREGATE_INITIALIZATION; + } } return null; } @@ -259,6 +332,8 @@ public class EvalTypeId extends CPPDependentEvaluation { short firstBytes = ITypeMarshalBuffer.EVAL_TYPE_ID; if (fRepresentsNewExpression) firstBytes |= ITypeMarshalBuffer.FLAG1; + if (fUsesBracedInitList) + firstBytes |= ITypeMarshalBuffer.FLAG2; buffer.putShort(firstBytes); buffer.marshalType(fInputType); @@ -280,7 +355,10 @@ public class EvalTypeId extends CPPDependentEvaluation { } IBinding templateDefinition= buffer.unmarshalBinding(); boolean forNewExpression = (firstBytes & ITypeMarshalBuffer.FLAG1) != 0; - return new EvalTypeId(type, templateDefinition, forNewExpression, args); + boolean usesBracedInitList = (firstBytes & ITypeMarshalBuffer.FLAG2) != 0; + EvalTypeId result = new EvalTypeId(type, templateDefinition, forNewExpression, usesBracedInitList, + args); + return result; } @Override @@ -290,7 +368,8 @@ public class EvalTypeId extends CPPDependentEvaluation { if (args == fArguments && type == fInputType) return this; - EvalTypeId result = new EvalTypeId(type, getTemplateDefinition(), fRepresentsNewExpression, args); + EvalTypeId result = new EvalTypeId(type, getTemplateDefinition(), fRepresentsNewExpression, + fUsesBracedInitList, args); if (!result.isTypeDependent()) { IType simplifiedType = SemanticUtil.getNestedType(type, SemanticUtil.TDEF); @@ -308,11 +387,17 @@ public class EvalTypeId extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPFunction constructor = getConstructor(null); + if (constructor != null && constructor instanceof ICPPConstructor) { + return new EvalConstructor(fInputType, (ICPPConstructor) constructor, fArguments, + getTemplateDefinition()).computeForFunctionCall(record, context); + } + ICPPEvaluation[] args = fArguments; for (int i = 0; i < fArguments.length; i++) { - ICPPEvaluation arg = fArguments[i].computeForFunctionCall(parameterMap, context.recordStep()); + ICPPEvaluation arg = fArguments[i].computeForFunctionCall(record, context.recordStep()); if (arg != fArguments[i]) { if (args == fArguments) { args = new ICPPEvaluation[fArguments.length]; @@ -321,9 +406,13 @@ public class EvalTypeId extends CPPDependentEvaluation { args[i] = arg; } } - if (args == fArguments) + + if (args == fArguments) { return this; - return new EvalTypeId(fInputType, getTemplateDefinition(), fRepresentsNewExpression, args); + } + EvalTypeId evalTypeId = new EvalTypeId(fInputType, getTemplateDefinition(), fRepresentsNewExpression, + fUsesBracedInitList, args); + return evalTypeId; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java index b29ba79c172..2c31e51a9ce 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java @@ -40,6 +40,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IPointerType; @@ -53,10 +54,11 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator; import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArithmeticConversion; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; @@ -69,10 +71,11 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics.LookupMode; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil.Pair; import org.eclipse.core.runtime.CoreException; public class EvalUnary extends CPPDependentEvaluation { - private static final ICPPEvaluation ZERO_EVAL = new EvalFixed(CPPSemantics.INT_TYPE, PRVALUE, Value.create(0)); + private static final ICPPEvaluation ZERO_EVAL = new EvalFixed(CPPSemantics.INT_TYPE, PRVALUE, IntegralValue.create(0)); private final int fOperator; private final ICPPEvaluation fArgument; @@ -82,6 +85,7 @@ public class EvalUnary extends CPPDependentEvaluation { private boolean fCheckedIsConstantExpression; private boolean fIsConstantExpression; + public EvalUnary(int operator, ICPPEvaluation operand, IBinding addressOfQualifiedNameBinding, IASTNode pointOfDefinition) { this(operator, operand, addressOfQualifiedNameBinding, findEnclosingTemplate(pointOfDefinition)); @@ -286,7 +290,7 @@ public class EvalUnary extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { if (isValueDependent()) - return Value.create(this); + return IntegralValue.create(this); ICPPEvaluation arg = fArgument; ICPPFunction overload = getOverload(point); @@ -294,15 +298,15 @@ public class EvalUnary extends CPPDependentEvaluation { ICPPFunctionType functionType = overload.getType(); IType[] parameterTypes = functionType.getParameterTypes(); if (parameterTypes.length == 0) - return Value.ERROR; + return IntegralValue.ERROR; IType targetType = parameterTypes[0]; arg = maybeApplyConversion(arg, targetType, point); if (!(overload instanceof CPPImplicitFunction)) { if (!overload.isConstexpr()) - return Value.ERROR; + return IntegralValue.ERROR; ICPPEvaluation eval = new EvalBinding(overload, null, (IBinding) null); - arg = new EvalFunctionCall(new ICPPEvaluation[] {eval, arg}, (IBinding) null); + arg = new EvalFunctionCall(new ICPPEvaluation[] {eval, arg}, null, (IBinding) null); return arg.getValue(point); } } @@ -311,32 +315,29 @@ public class EvalUnary extends CPPDependentEvaluation { case op_sizeof: { SizeAndAlignment info = SizeofCalculator.getSizeAndAlignment(fArgument.getType(point), point); - return info == null ? Value.UNKNOWN : Value.create(info.size); + return info == null ? IntegralValue.UNKNOWN : IntegralValue.create(info.size); } case op_alignOf: { SizeAndAlignment info = SizeofCalculator.getSizeAndAlignment(fArgument.getType(point), point); - return info == null ? Value.UNKNOWN : Value.create(info.alignment); + return info == null ? IntegralValue.UNKNOWN : IntegralValue.create(info.alignment); } case op_noexcept: - return Value.UNKNOWN; // TODO(sprigogin): Implement + return IntegralValue.UNKNOWN; // TODO(sprigogin): Implement case op_sizeofParameterPack: - return Value.UNKNOWN; // TODO(sprigogin): Implement + IValue opVal = fArgument.getValue(point); + return IntegralValue.create(opVal.numberOfSubValues()); case op_typeid: - return Value.UNKNOWN; // TODO(sprigogin): Implement + return IntegralValue.UNKNOWN; // TODO(sprigogin): Implement case op_throw: - return Value.UNKNOWN; // TODO(sprigogin): Implement + return IntegralValue.UNKNOWN; // TODO(sprigogin): Implement } IValue val = arg.getValue(point); if (val == null) - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; - Long num = val.numericalValue(); - if (num != null) { - return Value.evaluateUnaryExpression(fOperator, num); - } - return Value.create(this); + return ValueFactory.evaluateUnaryExpression(fOperator, val); } @Override @@ -390,16 +391,106 @@ public class EvalUnary extends CPPDependentEvaluation { return new EvalUnary(fOperator, argument, binding, getTemplateDefinition()); } + + private ICPPEvaluation createOperatorOverloadEvaluation(ICPPFunction overload, IASTNode point, ICPPEvaluation arg) { + if(overload instanceof ICPPMethod) { + EvalMemberAccess opAccess = new EvalMemberAccess(arg.getType(point), ValueCategory.LVALUE, overload, arg, false, point); + ICPPEvaluation[] args = new ICPPEvaluation[]{opAccess}; + return new EvalFunctionCall(args, arg, point); + } else { + EvalBinding op = new EvalBinding(overload, overload.getType(), point); + ICPPEvaluation[] args = new ICPPEvaluation[]{op, arg}; + return new EvalFunctionCall(args, null, point); + } + } + + private static boolean isModifyingOperation(int op) { + return op == op_prefixIncr || op == op_prefixDecr || op == op_postFixIncr || op == op_postFixDecr; + } + @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { - ICPPEvaluation argument = fArgument.computeForFunctionCall(parameterMap, context.recordStep()); - if (argument == fArgument) - return this; - - return new EvalUnary(fOperator, argument, fAddressOfQualifiedNameBinding, getTemplateDefinition()); + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPFunction overload = getOverload(context.getPoint()); + if (overload != null) { + ICPPEvaluation operatorCall = createOperatorOverloadEvaluation(overload, context.getPoint(), fArgument); + ICPPEvaluation eval = operatorCall.computeForFunctionCall(record, context); + return eval; + } + + Pair vp = EvalUtil.getValuePair(fArgument, record, context); + final ICPPEvaluation updateable = vp.getFirst(); + final ICPPEvaluation fixed = vp.getSecond(); + + ICPPEvaluation evalUnary = fixed == fArgument || fixed == EvalFixed.INCOMPLETE ? this : new EvalUnary(fOperator, fixed, fAddressOfQualifiedNameBinding, getTemplateDefinition()); + if(fOperator == op_star) { + if(fixed instanceof EvalPointer) { + EvalPointer evalPointer = (EvalPointer)fixed; + return evalPointer.dereference(); + } else if (updateable instanceof EvalBinding && isStarOperatorOnArrayName(context)) { + EvalBinding evalBinding = (EvalBinding)updateable; + IBinding binding = evalBinding.getBinding(); + ICPPEvaluation value = record.getVariable(binding); + EvalCompositeAccess compositeAccess = new EvalCompositeAccess(value, 0); + return new EvalReference(record, compositeAccess, getTemplateDefinition()); + } + return evalUnary; + } else if(fOperator == op_amper) { + if(updateable instanceof EvalBinding) { + EvalBinding evalBinding = (EvalBinding)updateable; + IBinding binding = evalBinding.getBinding(); + return new EvalPointer(record, binding, getTemplateDefinition()); + } else if(updateable instanceof EvalReference) { + EvalReference evalRef = (EvalReference)updateable; + return EvalPointer.createFromAddress(evalRef); + } + return evalUnary; + } else if(isModifyingOperation(fOperator)) { + if(fixed instanceof EvalPointer) { + EvalPointer evalPointer = (EvalPointer)fixed; + applyPointerArithmetics(evalPointer); + return evalPointer; + } else { + EvalFixed newValue = new EvalFixed(evalUnary.getType(context.getPoint()), evalUnary.getValueCategory(context.getPoint()), evalUnary.getValue(context.getPoint())); + if(updateable instanceof EvalReference) { + EvalReference evalRef = (EvalReference)updateable; + evalRef.update(newValue); + } else if(updateable instanceof EvalCompositeAccess) { + EvalCompositeAccess evalCompAccess = (EvalCompositeAccess)updateable; + evalCompAccess.update(newValue); + } else if(updateable instanceof EvalBinding) { + EvalBinding evalBinding = (EvalBinding)updateable; + IBinding binding = evalBinding.getBinding(); + record.update(binding, newValue); + } + + if (this.getValueCategory(context.getPoint()) == ValueCategory.LVALUE) { + return updateable; + } else { + return fixed; + } + } + } else { + return evalUnary; + } } + private boolean isStarOperatorOnArrayName(ConstexprEvaluationContext context) { + return fOperator==op_star && fArgument.getType(context.getPoint()) instanceof IArrayType; + } + + private void applyPointerArithmetics(EvalPointer poiner) { + switch(fOperator) { + case op_postFixIncr: + case op_prefixIncr: + poiner.setPosition(poiner.getPosition() + 1); + break; + case op_postFixDecr: + case op_prefixDecr: + poiner.setPosition(poiner.getPosition() - 1); + break; + } + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { return fArgument.determinePackSize(tpMap); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java index 202ae0e255c..dcbc61747c3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java @@ -46,8 +46,9 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; @@ -179,9 +180,9 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { @Override public IValue getValue(IASTNode point) { if (isValueDependent()) - return Value.create(this); + return IntegralValue.create(this); - return Value.evaluateUnaryTypeIdExpression(fOperator, fOrigType, point); + return ValueFactory.evaluateUnaryTypeIdExpression(fOperator, fOrigType, point); } @Override @@ -212,7 +213,7 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { return EvalFixed.INCOMPLETE; } else if (packSize != CPPTemplates.PACK_SIZE_DEFER) { IASTNode point = context.getPoint(); - return new EvalFixed(getType(point), getValueCategory(point), Value.create(packSize)); + return new EvalFixed(getType(point), getValueCategory(point), IntegralValue.create(packSize)); } } IType type = CPPTemplates.instantiateType(fOrigType, context); @@ -222,8 +223,7 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, - ConstexprEvaluationContext context) { + public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { return this; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java new file mode 100644 index 00000000000..2c00fdc55b3 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java @@ -0,0 +1,166 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; + +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecutionOwner; + +public class EvalUtil { + public static IValue getConditionExprValue(ICPPEvaluation conditionExprEval, ActivationRecord record, ConstexprEvaluationContext context) { + return conditionExprEval.computeForFunctionCall(record, context.recordStep()).getValue(context.getPoint()); + } + + public static IValue getConditionDeclValue(ExecSimpleDeclaration conditionDeclExec, ActivationRecord record, ConstexprEvaluationContext context) { + ICPPBinding declaredBinding = ((ExecDeclarator)conditionDeclExec.getDeclaratorExecutions()[0]).getDeclaredBinding(); + conditionDeclExec.executeForFunctionCall(record, context.recordStep()); + return record.getVariable(declaredBinding).computeForFunctionCall(record, context).getValue(context.getPoint()); + } + + public static boolean conditionExprSatisfied(ICPPEvaluation conditionExprEval, ActivationRecord record, ConstexprEvaluationContext context) { + Number result = getConditionExprValue(conditionExprEval, record, context).numberValue(); + return result != null && result.longValue() != 0; + } + + public static boolean conditionDeclSatisfied(ExecSimpleDeclaration conditionDeclExec, ActivationRecord record, ConstexprEvaluationContext context) { + Number result = getConditionDeclValue(conditionDeclExec, record, context).numberValue(); + return result != null && result.longValue() != 0; + } + + public static ICPPExecution getExecutionFromStatement(IASTStatement stmt) { + if(stmt instanceof ICPPExecutionOwner) { + ICPPExecutionOwner execOwner = (ICPPExecutionOwner)stmt; + return execOwner.getExecution(); + } + return null; + } + + // a return value != null means that there was a return, break or continue in that statement + public static ICPPExecution executeStatement(ICPPExecution exec, ActivationRecord record, ConstexprEvaluationContext context) { + if(exec instanceof ExecExpressionStatement + || exec instanceof ExecDeclarationStatement + || exec instanceof ExecCase + || exec instanceof ExecDefault) { + exec.executeForFunctionCall(record, context.recordStep()); + return null; + } else if(exec instanceof ExecCompoundStatement + || exec instanceof ExecWhile + || exec instanceof ExecFor + || exec instanceof ExecRangeBasedFor + || exec instanceof ExecDo + || exec instanceof ExecIf + || exec instanceof ExecSwitch) { + + ICPPExecution innerResult = exec.executeForFunctionCall(record, context.recordStep()); + if(innerResult instanceof ExecReturn || innerResult instanceof ExecBreak || innerResult instanceof ExecContinue) { + return innerResult; + } else if(innerResult != null) { + return ExecIncomplete.INSTANCE; + } + return null; + } else { + return exec; + } + } + + private static boolean isUpdateable(ICPPEvaluation eval) { + return eval instanceof EvalBinding || (eval instanceof EvalReference && !(eval instanceof EvalPointer)) || eval instanceof EvalCompositeAccess; + } + + /* + * Returns a pair of evaluations, each representing the value of 'eval'. + * The first, "updateable", is an lvalue (EvalBinding, EvalReference, or EvalCompositeAccess). + * The second, "fixed", is a value (usually EvalFixed or EvalPointer). + * We return both because, depending on the operation, we may need one representation or another. + */ + public static Pair getValuePair(ICPPEvaluation eval, ActivationRecord record, ConstexprEvaluationContext context) { + ICPPEvaluation updateable = null; + if(isUpdateable(eval)) { + updateable = eval; + } + ICPPEvaluation fixed = eval.computeForFunctionCall(record, context.recordStep()); + if(isUpdateable(fixed)) { + updateable = fixed; + if(!(fixed instanceof EvalCompositeAccess)) { + fixed = fixed.computeForFunctionCall(record, context); + } + } + return new Pair(updateable, fixed); + } + + public static class Pair { + private final T1 first; + private final T2 second; + + public Pair(T1 first, T2 second) { + this.first = first; + this.second = second; + } + + public T1 getFirst() { return first; } + public T2 getSecond() { return second; } + } + + public static boolean isCompilerGeneratedCtor(IBinding ctor) { + if(ctor instanceof ICPPSpecialization) { + ICPPSpecialization ctorSpec = (ICPPSpecialization)ctor; + return isCompilerGeneratedCtor(ctorSpec.getSpecializedBinding()); + } + return ctor instanceof ICPPConstructor && ((ICPPConstructor) ctor).isImplicit(); + } + + /** + * Get the initial value of the given variable, evaluated in the context of + * the given activation record. + */ + public static ICPPEvaluation getVariableValue(ICPPVariable variable, ActivationRecord record) { + IType type = variable.getType(); + IType nestedType = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); + IValue initialValue = variable.getInitialValue(); + ICPPEvaluation valueEval = null; + + if((initialValue != null && initialValue.getEvaluation() != null) || + (initialValue == null && nestedType instanceof ICPPClassType)) { + final ICPPEvaluation initializerEval = initialValue == null ? null : initialValue.getEvaluation(); + if(initializerEval == EvalFixed.INCOMPLETE) { + return null; + } + ExecDeclarator declaratorExec = new ExecDeclarator(variable, initializerEval); + + ConstexprEvaluationContext context = new ConstexprEvaluationContext(null); + if(declaratorExec.executeForFunctionCall(record, context) != ExecIncomplete.INSTANCE) { + valueEval = record.getVariable(declaratorExec.getDeclaredBinding()); + } + } else if(initialValue != null) { + valueEval = new EvalFixed(type, ValueCategory.LVALUE, initialValue); + } + + if(valueEval != null && (valueEval == EvalFixed.INCOMPLETE || + valueEval.getValue(null) == IntegralValue.UNKNOWN)) { + return null; + } + return valueEval; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecBreak.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecBreak.java new file mode 100644 index 00000000000..b07c60d172f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecBreak.java @@ -0,0 +1,37 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecBreak implements ICPPExecution { + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + return this; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + return this; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_BREAK); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + return new ExecBreak(); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecCase.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecCase.java new file mode 100644 index 00000000000..3de52a5b1ca --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecCase.java @@ -0,0 +1,60 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil.Pair; +import org.eclipse.core.runtime.CoreException; + +public class ExecCase implements ICPPExecution { + private final ICPPEvaluation caseExprEval; + + public ExecCase(ICPPEvaluation caseExprEval) { + this.caseExprEval = caseExprEval; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPEvaluation newCaseExprEval = caseExprEval.instantiate(context, maxDepth); + if (newCaseExprEval == caseExprEval) { + return this; + } + return new ExecCase(newCaseExprEval); + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + Pair vp = EvalUtil.getValuePair(caseExprEval, record, context); + ICPPEvaluation fixed = vp.getSecond(); + if(fixed == caseExprEval) { + return this; + } + return new ExecCase(fixed); + } + + public ICPPEvaluation getCaseExpressionEvaluation() { + return caseExprEval; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_CASE); + buffer.marshalEvaluation(caseExprEval, includeValue); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPEvaluation caseExprEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + return new ExecCase(caseExprEval); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecCompoundStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecCompoundStatement.java new file mode 100644 index 00000000000..c52e8a68f1f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecCompoundStatement.java @@ -0,0 +1,82 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecCompoundStatement implements ICPPExecution { + private ICPPExecution[] executions; + + private ExecCompoundStatement(ICPPExecution[] executions) { + this.executions = executions; + } + + public ExecCompoundStatement(IASTStatement[] statements) { + this(createExecutionsFromStatements(statements)); + } + + private static ICPPExecution[] createExecutionsFromStatements(IASTStatement[] statements) { + ICPPExecution[] executions = new ICPPExecution[statements.length]; + for(int i = 0; i < executions.length; i++) { + executions[i] = EvalUtil.getExecutionFromStatement(statements[i]); + } + return executions; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPExecution[] newExecutions = new ICPPExecution[executions.length]; + for(int i = 0; i < executions.length; i++) { + if(executions[i] == null) { + continue; + } + newExecutions[i] = executions[i].instantiate(context, maxDepth); + } + return new ExecCompoundStatement(newExecutions); + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + for(ICPPExecution execution : executions) { + if(execution == null) { + continue; + } + + ICPPExecution result = EvalUtil.executeStatement(execution, record, context); + if(result != null) { + return result; + } + } + return null; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_COMPOUND_STATEMENT); + buffer.putInt(executions.length); + for (ICPPExecution execution : executions) { + buffer.marshalExecution(execution, includeValue); + } + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + int len = buffer.getInt(); + ICPPExecution[] executions = new ICPPExecution[len]; + for (int i = 0; i < executions.length; i++) { + executions[i] = (ICPPExecution)buffer.unmarshalExecution(); + } + return new ExecCompoundStatement(executions); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecConstructorChain.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecConstructorChain.java new file mode 100644 index 00000000000..adbef955b48 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecConstructorChain.java @@ -0,0 +1,71 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecConstructorChain implements ICPPExecution { + private final Map ccInitializers; + + public ExecConstructorChain(Map ccInitializers) { + this.ccInitializers = ccInitializers; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + Map instantiatedInitializers = new HashMap<>(); + for (Entry initializer : ccInitializers.entrySet()) { + instantiatedInitializers.put( + CPPEvaluation.instantiateBinding(initializer.getKey(), context, maxDepth), + initializer.getValue().instantiate(context, maxDepth)); + } + return new ExecConstructorChain(instantiatedInitializers); + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + return this; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_CONSTRUCTOR_CHAIN); + buffer.putInt(ccInitializers.size()); + for (Entry ccInitializer : ccInitializers.entrySet()) { + buffer.marshalBinding(ccInitializer.getKey()); + buffer.marshalEvaluation(ccInitializer.getValue(), includeValue); + } + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + int len = buffer.getInt(); + Map ccInitializers = new HashMap<>(); + for (int i = 0; i < len; i++) { + IBinding member = buffer.unmarshalBinding(); + ICPPEvaluation memberEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + ccInitializers.put(member, memberEval); + } + return new ExecConstructorChain(ccInitializers); + } + + public Map getConstructorChainInitializers() { + return ccInitializers; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecContinue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecContinue.java new file mode 100644 index 00000000000..c4ecc8e0db5 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecContinue.java @@ -0,0 +1,37 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecContinue implements ICPPExecution { + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + return this; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + return this; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_CONTINUE); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + return new ExecContinue(); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarationStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarationStatement.java new file mode 100644 index 00000000000..7ee5a9f2ea3 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarationStatement.java @@ -0,0 +1,53 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecDeclarationStatement implements ICPPExecution { + private final ICPPExecution declarationExec; + + public ExecDeclarationStatement(ICPPExecution declarationExec) { + this.declarationExec = declarationExec; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPExecution newDeclarationExec = declarationExec.instantiate(context, maxDepth); + if (newDeclarationExec == declarationExec) { + return this; + } + return new ExecDeclarationStatement(newDeclarationExec); + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPExecution newDeclarationExec = declarationExec.executeForFunctionCall(record, context); + if (newDeclarationExec == declarationExec) { + return this; + } + return new ExecDeclarationStatement(newDeclarationExec); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_DECLARATION_STATEMENT); + buffer.marshalExecution(declarationExec, includeValue); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPExecution declarationExec = (ICPPExecution)buffer.unmarshalExecution(); + return new ExecDeclarationStatement(declarationExec); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarator.java new file mode 100644 index 00000000000..15dbb0669b6 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDeclarator.java @@ -0,0 +1,219 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; + +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; +import org.eclipse.cdt.core.dom.ast.IArrayType; +import org.eclipse.cdt.core.dom.ast.IPointerType; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; +import org.eclipse.cdt.internal.core.dom.parser.CompositeValue; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecDeclarator implements ICPPExecution { + private final ICPPBinding declaredBinding; + private final ICPPEvaluation initializerEval; + + public ExecDeclarator(ICPPBinding declaredBinding, ICPPEvaluation initializerEval) { + this.declaredBinding = declaredBinding; + this.initializerEval = initializerEval; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + if(!(declaredBinding instanceof ICPPVariable)) { + return this; + } + + ICPPVariable declaredVariable = (ICPPVariable)declaredBinding; + IType type = declaredVariable.getType(); + ICPPEvaluation initialValue = createInitialValue(type, record, context); + if(initialValue == null || initialValue == EvalFixed.INCOMPLETE) { + return ExecIncomplete.INSTANCE; + } + + record.update(declaredBinding, initialValue); + return this; + } + + public ICPPBinding getDeclaredBinding() { + return declaredBinding; + } + + private ICPPEvaluation createInitialValue(IType type, ActivationRecord record, ConstexprEvaluationContext context) { + if(initializerEval == null) { + return createDefaultInitializedCompositeValue(type); + } + + ICPPEvaluation computedInitializerEval = initializerEval.computeForFunctionCall(record, context.recordStep()); + + //if a compositevalue with only one member is initialized with an initializer list + //it evaluates to a EvalFixed with a Value instead of a CompositeValue because the initializer list + //doesn't know that it is initializing a composite. + IType nestedType = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); + if(isClassType(nestedType) && computedInitializerEval instanceof EvalFixed) { + EvalFixed evalFixed = (EvalFixed) computedInitializerEval; + IValue val = evalFixed.getValue(); + if(!(val instanceof CompositeValue)) { + CompositeValue compVal = new CompositeValue(initializerEval, new ICPPEvaluation[]{evalFixed}); + computedInitializerEval = new EvalFixed(type, computedInitializerEval.getValueCategory(context.getPoint()), compVal); + } + } + + if (isReferenceType(type)) { + return createReferenceValue(record, context, computedInitializerEval); + } else if (isPointerType(nestedType) && !isCStringType(nestedType)) { + return createPointerValue(record, context, computedInitializerEval); + } else if(isArrayType(nestedType) && !isCStringType(nestedType)) { + IValue value = CompositeValue.create((EvalInitList)computedInitializerEval,(IArrayType) (type)); + return new EvalFixed(type, computedInitializerEval.getValueCategory(context.getPoint()), value); + } else if (isValueInitialization(computedInitializerEval)){ + ICPPEvaluation defaultValue = new EvalTypeId(type, context.getPoint(), false, new ICPPEvaluation[]{}); + return new EvalFixed(type, defaultValue.getValueCategory(context.getPoint()), defaultValue.getValue(context.getPoint())); + } else { + return new EvalFixed(type, computedInitializerEval.getValueCategory(context.getPoint()), computedInitializerEval.getValue(context.getPoint())); + } + } + + private static ICPPEvaluation createDefaultInitializedCompositeValue(IType type) { + if(!isClassType(type)) { + return EvalFixed.INCOMPLETE; + } + ICPPClassType classType = (ICPPClassType)type; + // TODO(nathanridge): CompositeValue.create() only consider default member initializers, not + // constructors. Should we be considering constructors here as well? + IValue compositeValue = CompositeValue.create(classType); + EvalFixed initialValue = new EvalFixed(type, ValueCategory.PRVALUE, compositeValue); + return initialValue; + } + + private ICPPEvaluation createReferenceValue(ActivationRecord record, ConstexprEvaluationContext context, ICPPEvaluation computedInitializerEval) { + ICPPEvaluation initValue = initializerEval; + if(!(initValue instanceof EvalBinding)) { + initValue = initializerEval.getValue(context.getPoint()).getSubValue(0); + } + + if(initValue instanceof EvalBinding) { + return createReferenceFromBinding(record, context, (EvalBinding) initValue); + } else if(initValue instanceof EvalBinary && computedInitializerEval instanceof EvalCompositeAccess) { + return createReferenceFromCompositeAccess(record, context, (EvalCompositeAccess) computedInitializerEval); + } else { + return EvalFixed.INCOMPLETE; + } + } + + private ICPPEvaluation createPointerValue(ActivationRecord record, ConstexprEvaluationContext context, ICPPEvaluation computedInitializerEval) { + ICPPEvaluation initValue = initializerEval.getValue(context.getPoint()).getSubValue(0); + if (isPointerToArray(initValue, context)) { + EvalCompositeAccess arrayPointer = new EvalCompositeAccess(computedInitializerEval, 0); + return createPointerFromCompositeAccess(record, context, arrayPointer); + } else if (computedInitializerEval instanceof EvalPointer) { + EvalPointer pointer = (EvalPointer)computedInitializerEval; + return pointer.copy(); + } + return EvalFixed.INCOMPLETE; + } + + private static boolean isValueInitialization(ICPPEvaluation eval) { + if(eval instanceof EvalInitList) { + EvalInitList evalInitList = (EvalInitList)eval; + return evalInitList.getClauses().length == 0; + } + return false; + } + + private static boolean isPointerToArray(ICPPEvaluation eval, ConstexprEvaluationContext context) { + return eval.getType(context.getPoint()) instanceof IArrayType; + } + + private static ICPPEvaluation createReferenceFromBinding(ActivationRecord record, ConstexprEvaluationContext context, EvalBinding evalBinding) { + return new EvalReference(record, evalBinding.getBinding(), context.getPoint()); + } + + private static ICPPEvaluation createReferenceFromCompositeAccess(ActivationRecord record, ConstexprEvaluationContext context, EvalCompositeAccess evalCompAccess) { + return new EvalReference(record, evalCompAccess, context.getPoint()); + } + + private static ICPPEvaluation createPointerFromCompositeAccess(ActivationRecord record, ConstexprEvaluationContext context, EvalCompositeAccess evalCompAccess) { + return new EvalPointer(record, evalCompAccess, context.getPoint()); + } + + private static boolean isReferenceType(IType type) { + return type instanceof ICPPReferenceType; + } + + private static boolean isPointerType(IType type) { + return type instanceof IPointerType; + } + + private static boolean isArrayType(IType type) { + return type instanceof IArrayType; + } + + private static boolean isCStringType(IType type) { + IType nestedType = null; + if(type instanceof IArrayType) { + nestedType = ((IArrayType)type).getType(); + } else if(type instanceof IPointerType) { + nestedType = ((IPointerType)type).getType(); + } + + if(nestedType != null) { + return nestedType.isSameType(new CPPQualifierType(CPPBasicType.CHAR, true, false)); + } + return false; + } + + private static boolean isClassType(IType type) { + return type instanceof ICPPClassType; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPBinding newDeclaredBinding; + if(declaredBinding instanceof ICPPVariable) { + ICPPVariable declaredVariable = (ICPPVariable)declaredBinding; + newDeclaredBinding = CPPTemplates.createVariableSpecialization(context, declaredVariable); + } else { + newDeclaredBinding = (ICPPBinding)CPPTemplates.createSpecialization(context.getContextSpecialization(), declaredBinding, context.getPoint()); + } + + ICPPEvaluation newInitializerEval = initializerEval != null ? initializerEval.instantiate(context, maxDepth) : null; + return new ExecDeclarator(newDeclaredBinding, newInitializerEval); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_DECLARATOR); + buffer.marshalBinding(declaredBinding); + buffer.marshalEvaluation(initializerEval, includeValue); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPBinding declaredBinding = (ICPPBinding)buffer.unmarshalBinding(); + ICPPEvaluation initializerEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + return new ExecDeclarator(declaredBinding, initializerEval); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDefault.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDefault.java new file mode 100644 index 00000000000..82e4eead7d5 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDefault.java @@ -0,0 +1,37 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecDefault implements ICPPExecution { + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + return this; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + return this; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_DEFAULT); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + return new ExecDefault(); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDo.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDo.java new file mode 100644 index 00000000000..4ec8019bda4 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecDo.java @@ -0,0 +1,67 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecDo implements ICPPExecution { + private final ICPPEvaluation conditionEval; + private final ICPPExecution bodyExec; + + public ExecDo(ICPPEvaluation conditionEval, ICPPExecution bodyExec) { + this.conditionEval = conditionEval; + this.bodyExec = bodyExec; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + do { + if (context.getStepsPerformed() >= ConstexprEvaluationContext.MAX_CONSTEXPR_EVALUATION_STEPS) { + return ExecIncomplete.INSTANCE; + } + + ICPPExecution result = EvalUtil.executeStatement(bodyExec, record, context); + if(result instanceof ExecReturn) { + return result; + } else if(result instanceof ExecBreak) { + break; + } + } while (EvalUtil.conditionExprSatisfied(conditionEval, record, context)); + return null; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPEvaluation newConditionEval = conditionEval.instantiate(context, maxDepth); + ICPPExecution newBodyExec = bodyExec.instantiate(context, maxDepth); + if(newConditionEval == conditionEval && newBodyExec == bodyExec) { + return this; + } + return new ExecDo(newConditionEval, newBodyExec); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_DO); + buffer.marshalEvaluation(conditionEval, includeValue); + buffer.marshalExecution(bodyExec, includeValue); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPEvaluation conditionEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + ICPPExecution bodyExec = (ICPPExecution)buffer.unmarshalExecution(); + return new ExecDo(conditionEval, bodyExec); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecExpressionStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecExpressionStatement.java new file mode 100644 index 00000000000..3d9721c4385 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecExpressionStatement.java @@ -0,0 +1,54 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecExpressionStatement implements ICPPExecution { + private ICPPEvaluation exprEval; + + public ExecExpressionStatement(ICPPEvaluation exprEval) { + this.exprEval = exprEval; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPEvaluation newExprEval = exprEval.instantiate(context, maxDepth); + if (newExprEval == exprEval) { + return this; + } + return new ExecExpressionStatement(newExprEval); + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPEvaluation newExprEval = exprEval.computeForFunctionCall(record, context); + if (newExprEval == exprEval) { + return this; + } + return new ExecExpressionStatement(newExprEval); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_EXPRESSION_STATEMENT); + buffer.marshalEvaluation(exprEval, includeValue); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPEvaluation exprEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + return new ExecExpressionStatement(exprEval); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecFor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecFor.java new file mode 100644 index 00000000000..d737b44e5aa --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecFor.java @@ -0,0 +1,109 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecFor implements ICPPExecution { + private final ICPPExecution initializerExec; + private final ICPPEvaluation conditionExprEval; + private final ExecSimpleDeclaration conditionDeclExec; + private final ICPPEvaluation iterationEval; + private final ICPPExecution bodyExec; + + public ExecFor(ICPPExecution initializerExec, ICPPEvaluation conditionExprEval, ExecSimpleDeclaration conditionDeclExec, ICPPEvaluation iterationEval, ICPPExecution bodyExec) { + this.initializerExec = initializerExec; + this.conditionExprEval = conditionExprEval; + this.conditionDeclExec = conditionDeclExec; + this.iterationEval = iterationEval; + this.bodyExec = bodyExec; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + for(evaluateInitializationStatement(record, context); conditionSatisfied(record, context); evaluateIterationExpression(record, context)) { + if (context.getStepsPerformed() >= ConstexprEvaluationContext.MAX_CONSTEXPR_EVALUATION_STEPS) { + return ExecIncomplete.INSTANCE; + } + + ICPPExecution result = EvalUtil.executeStatement(bodyExec, record, context); + if(result instanceof ExecReturn) { + return result; + } else if(result instanceof ExecBreak) { + break; + } else if(result instanceof ExecContinue) { + continue; + } + } + return null; + } + + private void evaluateInitializationStatement(ActivationRecord record, ConstexprEvaluationContext context) { + if (initializerExec != null) { + EvalUtil.executeStatement(initializerExec, record, context); + } + } + + private boolean conditionSatisfied(ActivationRecord record, ConstexprEvaluationContext context) { + if(conditionExprEval != null) { + return EvalUtil.conditionExprSatisfied(conditionExprEval, record, context); + } else if(conditionDeclExec != null) { + return EvalUtil.conditionDeclSatisfied(conditionDeclExec, record, context); + } + return true; + } + + private void evaluateIterationExpression(ActivationRecord record, ConstexprEvaluationContext context) { + if (iterationEval != null) { + iterationEval.computeForFunctionCall(record, context); + } + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPExecution newInitializerExec = initializerExec != null ? initializerExec.instantiate(context, maxDepth) : null; + ICPPEvaluation newConditionExprEval = conditionExprEval != null ? conditionExprEval.instantiate(context, maxDepth) : null; + ExecSimpleDeclaration newConditionDeclExec = conditionDeclExec != null ? (ExecSimpleDeclaration)conditionDeclExec.instantiate(context, maxDepth) : null; + ICPPEvaluation newIterationEval = iterationEval != null ? iterationEval.instantiate(context, maxDepth) : null; + ICPPExecution newBodyExec = bodyExec.instantiate(context, maxDepth); + if (newInitializerExec == initializerExec && + newConditionExprEval == conditionExprEval && + newConditionDeclExec == conditionDeclExec && + newIterationEval == iterationEval && + newBodyExec == bodyExec) { + return this; + } + return new ExecFor(newInitializerExec, newConditionExprEval, newConditionDeclExec, newIterationEval, newBodyExec); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_FOR); + buffer.marshalExecution(initializerExec, includeValue); + buffer.marshalEvaluation(conditionExprEval, includeValue); + buffer.marshalExecution(conditionDeclExec, includeValue); + buffer.marshalEvaluation(iterationEval, includeValue); + buffer.marshalExecution(bodyExec, includeValue); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPExecution initializerExec = (ICPPExecution)buffer.unmarshalExecution(); + ICPPEvaluation conditionExprEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + ExecSimpleDeclaration conditionDeclExec = (ExecSimpleDeclaration)buffer.unmarshalExecution(); + ICPPEvaluation iterationEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + ICPPExecution bodyExec = (ICPPExecution)buffer.unmarshalExecution(); + return new ExecFor(initializerExec, conditionExprEval, conditionDeclExec, iterationEval, bodyExec); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecIf.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecIf.java new file mode 100644 index 00000000000..089af247fea --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecIf.java @@ -0,0 +1,77 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecIf implements ICPPExecution { + private final ICPPEvaluation conditionExprEval; + private final ExecSimpleDeclaration conditionDeclExec; + private final ICPPExecution thenClauseExec; + private final ICPPExecution elseClauseExec; + + public ExecIf(ICPPEvaluation conditionExprEval, ExecSimpleDeclaration conditionDeclExec, ICPPExecution thenClauseExec, ICPPExecution elseClauseExec) { + this.conditionExprEval = conditionExprEval; + this.conditionDeclExec = conditionDeclExec; + this.thenClauseExec = thenClauseExec; + this.elseClauseExec = elseClauseExec; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + boolean conditionSatisfied = false; + if(conditionExprEval != null) { + conditionSatisfied = EvalUtil.conditionExprSatisfied(conditionExprEval, record, context); + } else if(conditionDeclExec != null) { + conditionSatisfied = EvalUtil.conditionDeclSatisfied(conditionDeclExec, record, context); + } + + if(conditionSatisfied) { + return EvalUtil.executeStatement(thenClauseExec, record, context); + } else if(elseClauseExec != null) { + return EvalUtil.executeStatement(elseClauseExec, record, context); + } + return null; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPEvaluation newConditionExprEval = conditionExprEval != null ? conditionExprEval.instantiate(context, maxDepth) : null; + ExecSimpleDeclaration newConditionDeclExec = conditionDeclExec != null ? (ExecSimpleDeclaration)conditionDeclExec.instantiate(context, maxDepth) : null; + ICPPExecution newThenClauseExec = thenClauseExec.instantiate(context, maxDepth); + ICPPExecution newElseClauseExec = elseClauseExec != null ? elseClauseExec.instantiate(context, maxDepth) : null; + if (newConditionExprEval == conditionExprEval && newConditionDeclExec == conditionDeclExec && newThenClauseExec == thenClauseExec && newElseClauseExec == elseClauseExec) { + return this; + } + return new ExecIf(newConditionExprEval, newConditionDeclExec, newThenClauseExec, newElseClauseExec); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_IF); + buffer.marshalEvaluation(conditionExprEval, includeValue); + buffer.marshalExecution(conditionDeclExec, includeValue); + buffer.marshalExecution(thenClauseExec, includeValue); + buffer.marshalExecution(elseClauseExec, includeValue); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPEvaluation conditionExprEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + ExecSimpleDeclaration conditionDeclExec = (ExecSimpleDeclaration)buffer.unmarshalExecution(); + ICPPExecution thenClauseExec = (ICPPExecution)buffer.unmarshalExecution(); + ICPPExecution elseClauseExec = (ICPPExecution)buffer.unmarshalExecution(); + return new ExecIf(conditionExprEval, conditionDeclExec, thenClauseExec, elseClauseExec); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecIncomplete.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecIncomplete.java new file mode 100644 index 00000000000..4e316f2627f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecIncomplete.java @@ -0,0 +1,36 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecIncomplete implements ICPPExecution { + public static ExecIncomplete INSTANCE = new ExecIncomplete(); + + private ExecIncomplete() {} + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + return this; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + return this; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + throw new UnsupportedOperationException(); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecRangeBasedFor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecRangeBasedFor.java new file mode 100644 index 00000000000..67eb6094850 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecRangeBasedFor.java @@ -0,0 +1,197 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; + +import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; +import org.eclipse.cdt.core.dom.ast.IArrayType; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IVariable; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecRangeBasedFor implements ICPPExecution { + private final ExecSimpleDeclaration declarationExec; + private final ICPPEvaluation initClauseEval; + private final ICPPFunction begin; + private final ICPPFunction end; + private final ICPPExecution bodyExec; + + public ExecRangeBasedFor(ExecSimpleDeclaration declarationExec, ICPPEvaluation initClauseEval, ICPPFunction begin, ICPPFunction end, ICPPExecution bodyExec) { + this.declarationExec = declarationExec; + this.initClauseEval = initClauseEval; + this.begin = begin; + this.end = end; + this.bodyExec = bodyExec; + } + + private ICPPExecution loopOverArray(IVariable rangeVar, ICPPEvaluation valueRange, ActivationRecord record, ConstexprEvaluationContext context) { + ICPPEvaluation[] range = valueRange.getValue(context.getPoint()).getAllSubValues(); + for(int i = 0; i < range.length; i++ ) { + ICPPEvaluation value = new EvalFixed(range[i].getType(context.getPoint()), range[i].getValueCategory(context.getPoint()), range[i].getValue(context.getPoint())); + if(rangeVar.getType() instanceof ICPPReferenceType) { + value = new EvalReference(record, new EvalCompositeAccess(valueRange, i), value.getTemplateDefinition()); + } + record.update(rangeVar, value); + + ICPPExecution result = EvalUtil.executeStatement(bodyExec, record, context); + if(result instanceof ExecReturn) { + return result; + } else if(result instanceof ExecBreak) { + break; + } else if(result instanceof ExecContinue) { + continue; + } + } + return null; + } + + private ICPPExecution loopOverObject(IVariable rangeVar, ICPPEvaluation rangeEval, boolean rangeIsConst, ICPPClassType classType, ActivationRecord record, ConstexprEvaluationContext context) { + if(begin != null && end != null) { + ICPPEvaluation beginEval = callFunction(classType, begin, rangeEval, record, context); + ICPPEvaluation endEval = callFunction(classType, end, rangeEval, record, context); + boolean isRef = rangeVar.getType() instanceof ICPPReferenceType; + + for(; !isEqual(beginEval, endEval, context.getPoint()); beginEval = inc(record, beginEval, context)) { + record.update(rangeVar, deref(beginEval, isRef, record, context)); + + ICPPExecution result = EvalUtil.executeStatement(bodyExec, record, context); + if(result instanceof ExecReturn) { + return result; + } else if(result instanceof ExecBreak) { + break; + } else if(result instanceof ExecContinue) { + continue; + } + } + return null; + } + return ExecIncomplete.INSTANCE; + } + + private static boolean isEqual(ICPPEvaluation a, ICPPEvaluation b, IASTNode point) { + Number result = new EvalBinary(IASTBinaryExpression.op_equals, a, b, point).getValue(point).numberValue(); + return result != null && result.longValue() != 0; + } + + private static ICPPEvaluation deref(ICPPEvaluation ptr, boolean isRef, ActivationRecord record, ConstexprEvaluationContext context) { + ICPPEvaluation derefEval = new EvalUnary(ICPPASTUnaryExpression.op_star, ptr, null, context.getPoint()).computeForFunctionCall(record, context); + if(isRef) { + return derefEval; + } else { + return new EvalFixed(derefEval.getType(context.getPoint()), derefEval.getValueCategory(context.getPoint()), derefEval.getValue(context.getPoint())); + } + } + + private static ICPPEvaluation inc(ActivationRecord record, ICPPEvaluation ptr, + ConstexprEvaluationContext context) { + return new EvalUnary(IASTUnaryExpression.op_prefixIncr, ptr, null, context.getPoint()) + .computeForFunctionCall(record, context); + } + + private static ICPPEvaluation callFunction(ICPPClassType classType, ICPPFunction func, ICPPEvaluation rangeEval, ActivationRecord record, ConstexprEvaluationContext context) { + EvalFunctionCall call = null; + if(func instanceof ICPPMethod) { + EvalMemberAccess memberAccess = new EvalMemberAccess(classType, ValueCategory.LVALUE, func, rangeEval, false, context.getPoint()); + ICPPEvaluation[] args = new ICPPEvaluation[]{ memberAccess }; + call = new EvalFunctionCall(args, rangeEval, context.getPoint()); + } else { + EvalBinding op = new EvalBinding(func, func.getType(), context.getPoint()); + ICPPEvaluation[] args = new ICPPEvaluation[]{ op, rangeEval}; + call = new EvalFunctionCall(args, null, context.getPoint()); + } + return call.computeForFunctionCall(record, context); + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + if (context.getStepsPerformed() >= ConstexprEvaluationContext.MAX_CONSTEXPR_EVALUATION_STEPS) { + return ExecIncomplete.INSTANCE; + } + + ICPPEvaluation valueRange = initClauseEval.computeForFunctionCall(record, context.recordStep()); + ExecDeclarator declaratorExec = (ExecDeclarator) declarationExec.getDeclaratorExecutions()[0]; + IVariable rangeVar = (IVariable)declaratorExec.getDeclaredBinding(); + + boolean rangeIsConst = SemanticUtil.isConst(initClauseEval.getType(context.getPoint())); + IType type = SemanticUtil.getNestedType(valueRange.getType(context.getPoint()), ALLCVQ | TDEF | REF); + if(type instanceof IArrayType || type instanceof InitializerListType) { + return loopOverArray(rangeVar, valueRange, record, context); + } else if(type instanceof ICPPClassType) { + ICPPClassType classType = (ICPPClassType)type; + return loopOverObject(rangeVar, initClauseEval, rangeIsConst, classType, record, context); + } + return ExecIncomplete.INSTANCE; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ExecSimpleDeclaration newDeclarationExec = (ExecSimpleDeclaration)declarationExec.instantiate(context, maxDepth); + ICPPEvaluation newInitClauseEval = initClauseEval.instantiate(context, maxDepth); + // TODO: This isn't the correct way to instantiate the 'begin' and 'end' functions, because + // if the range type is dependent, ADL may find different functions to call after instantiation. + // The correct way would be: + // - Construct EvalFunctionCalls representing the invocations of begin and end with the + // range as argument. + // - Instantiate the EvalFunctionCalls. This will perform the ADL if appropriate. + // - Query the instantiated function bindings from the instantiated EvalFunctionCalls. + // Alternatively, we could lower the range-based for loop into a regular for loop as + // described in the standard (by constructing the corresponding executions and evaluations), + // and the above instantiations will fall out of that automatically. + ICPPFunction newBegin = begin != null ? (ICPPFunction)CPPTemplates.createSpecialization( + context.getContextSpecialization(), begin, context.getPoint()) : null; + ICPPFunction newEnd = end != null ? (ICPPFunction)CPPTemplates.createSpecialization( + context.getContextSpecialization(), end, context.getPoint()) : null; + ICPPExecution newBodyExec = bodyExec.instantiate(context, maxDepth); + + if (newDeclarationExec == declarationExec && + newInitClauseEval == initClauseEval && + newBegin == begin && + newEnd == end && + newBodyExec == bodyExec) { + return this; + } + return new ExecRangeBasedFor(newDeclarationExec, newInitClauseEval, newBegin, newEnd, newBodyExec); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_RANGE_BASED_FOR); + buffer.marshalExecution(declarationExec, includeValue); + buffer.marshalEvaluation(initClauseEval, includeValue); + buffer.marshalBinding(begin); + buffer.marshalBinding(end); + buffer.marshalExecution(bodyExec, includeValue); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ExecSimpleDeclaration declarationExec = (ExecSimpleDeclaration)buffer.unmarshalExecution(); + ICPPEvaluation initClauseEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + ICPPFunction begin = (ICPPFunction)buffer.unmarshalBinding(); + ICPPFunction end = (ICPPFunction)buffer.unmarshalBinding(); + ICPPExecution bodyExec = (ICPPExecution)buffer.unmarshalExecution(); + return new ExecRangeBasedFor(declarationExec, initClauseEval, begin, end, bodyExec); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecReturn.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecReturn.java new file mode 100644 index 00000000000..8a55f1b0e7d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecReturn.java @@ -0,0 +1,58 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecReturn implements ICPPExecution { + private ICPPEvaluation retVal; + + public ExecReturn(ICPPEvaluation exprEval) { + this.retVal = exprEval; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPEvaluation newRetVal = retVal.instantiate(context, maxDepth); + if (newRetVal == retVal) { + return this; + } + return new ExecReturn(newRetVal); + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPEvaluation newRetVal = retVal.computeForFunctionCall(record, context); + if (newRetVal == retVal) { + return this; + } + return new ExecReturn(newRetVal); + } + + public ICPPEvaluation getReturnValueEvaluation() { + return retVal; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_RETURN); + buffer.marshalEvaluation(retVal, includeValue); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPEvaluation retVal = (ICPPEvaluation)buffer.unmarshalEvaluation(); + return new ExecReturn(retVal); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecSimpleDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecSimpleDeclaration.java new file mode 100644 index 00000000000..61af70678e2 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecSimpleDeclaration.java @@ -0,0 +1,64 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecSimpleDeclaration implements ICPPExecution { + private final ICPPExecution[] declaratorExecutions; + + public ExecSimpleDeclaration(ICPPExecution[] declaratorExecutions) { + this.declaratorExecutions = declaratorExecutions; + } + + public ICPPExecution[] getDeclaratorExecutions() { + return declaratorExecutions; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + ICPPExecution[] newDeclaratorExecutions = new ICPPExecution[declaratorExecutions.length]; + for(int i = 0; i < declaratorExecutions.length; i++) { + newDeclaratorExecutions[i] = declaratorExecutions[i].executeForFunctionCall(record, context); + } + return new ExecSimpleDeclaration(newDeclaratorExecutions); + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPExecution[] newDeclaratorExecutions = new ICPPExecution[declaratorExecutions.length]; + for(int i = 0; i < declaratorExecutions.length; i++) { + newDeclaratorExecutions[i] = declaratorExecutions[i].instantiate(context, maxDepth); + } + return new ExecSimpleDeclaration(newDeclaratorExecutions); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_SIMPLE_DECLARATION); + buffer.putInt(declaratorExecutions.length); + for (ICPPExecution execution : declaratorExecutions) { + buffer.marshalExecution(execution, includeValue); + } + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + int len = buffer.getInt(); + ICPPExecution[] declaratorExecutions = new ICPPExecution[len]; + for (int i = 0; i < declaratorExecutions.length; i++) { + declaratorExecutions[i] = (ICPPExecution)buffer.unmarshalExecution(); + } + return new ExecSimpleDeclaration(declaratorExecutions); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecSwitch.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecSwitch.java new file mode 100644 index 00000000000..a5861d49ed2 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecSwitch.java @@ -0,0 +1,115 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecSwitch implements ICPPExecution { + private final ICPPEvaluation controllerExprEval; + private final ExecSimpleDeclaration controllerDeclExec; + private final ICPPExecution[] bodyStmtExecutions; + + public ExecSwitch(ICPPEvaluation controllerExprEval, ExecSimpleDeclaration controllerDeclExec, ICPPExecution[] bodyStmtExecutions) { + this.controllerExprEval = controllerExprEval; + this.controllerDeclExec = controllerDeclExec; + this.bodyStmtExecutions = bodyStmtExecutions; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + final int caseIndex = getMatchingCaseIndex(record, context); + for(int i = caseIndex; i < bodyStmtExecutions.length; ++i) { + ICPPExecution stmtExec = bodyStmtExecutions[i]; + ICPPExecution result = EvalUtil.executeStatement(stmtExec, record, context); + if(result instanceof ExecReturn || result instanceof ExecContinue) { + return result; + } else if(result instanceof ExecBreak) { + break; + } + } + return null; + } + + private int getMatchingCaseIndex(ActivationRecord record, ConstexprEvaluationContext context) { + IValue controllerValue = null; + if(controllerExprEval != null) { + controllerValue = EvalUtil.getConditionExprValue(controllerExprEval, record, context); + } else if(controllerDeclExec != null) { + controllerValue = EvalUtil.getConditionDeclValue(controllerDeclExec, record, context); + } + + for(int i = 0; i < bodyStmtExecutions.length; ++i) { + if(isSatisfiedCaseStatement(bodyStmtExecutions[i], controllerValue, record, context)) { + return i; + } + } + return bodyStmtExecutions.length; + } + + private boolean isSatisfiedCaseStatement(ICPPExecution stmtExec, IValue controllerValue, ActivationRecord record, ConstexprEvaluationContext context) { + if (stmtExec instanceof ExecCase) { + ExecCase caseStmtExec = (ExecCase)stmtExec; + caseStmtExec = (ExecCase)caseStmtExec.executeForFunctionCall(record, context); + Number caseVal = caseStmtExec.getCaseExpressionEvaluation().getValue(null).numberValue(); + Number controllerVal = controllerValue.numberValue(); + return caseVal.equals(controllerVal); + } + return stmtExec instanceof ExecDefault; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPEvaluation newControllerExprEval = controllerExprEval != null ? controllerExprEval.instantiate(context, maxDepth) : null; + ExecSimpleDeclaration newControllerDeclExec = controllerDeclExec != null ? (ExecSimpleDeclaration)controllerDeclExec.instantiate(context, maxDepth) : null; + ICPPExecution[] newBodyStmtExecutions = new ICPPExecution[bodyStmtExecutions.length]; + boolean executionsDidChange = false; + for(int i = 0; i < bodyStmtExecutions.length; i++) { + ICPPExecution bodyStmtExec = bodyStmtExecutions[i]; + ICPPExecution newBodyStmtExec = bodyStmtExec.instantiate(context, maxDepth); + if(newBodyStmtExec != bodyStmtExec) { + executionsDidChange = true; + } + newBodyStmtExecutions[i] = newBodyStmtExec; + } + + if (newControllerExprEval == controllerExprEval && newControllerDeclExec == controllerDeclExec && !executionsDidChange) { + return this; + } + return new ExecSwitch(newControllerExprEval, newControllerDeclExec, newBodyStmtExecutions); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_SWITCH); + buffer.marshalEvaluation(controllerExprEval, includeValue); + buffer.marshalExecution(controllerDeclExec, includeValue); + buffer.putInt(bodyStmtExecutions.length); + for (ICPPExecution execution : bodyStmtExecutions) { + buffer.marshalExecution(execution, includeValue); + } + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPEvaluation controllerExprEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + ExecSimpleDeclaration controllerDeclExec = (ExecSimpleDeclaration)buffer.unmarshalExecution(); + int len = buffer.getInt(); + ICPPExecution[] bodyStmtExecutions = new ICPPExecution[len]; + for (int i = 0; i < bodyStmtExecutions.length; i++) { + bodyStmtExecutions[i] = (ICPPExecution)buffer.unmarshalExecution(); + } + return new ExecSwitch(controllerExprEval, controllerDeclExec, bodyStmtExecutions); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecWhile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecWhile.java new file mode 100644 index 00000000000..36871f5a9de --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecWhile.java @@ -0,0 +1,83 @@ +/******************************************************************************* +* Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik +* Rapperswil, University of applied sciences and others +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +public class ExecWhile implements ICPPExecution { + private final ICPPEvaluation conditionExprEval; + private final ExecSimpleDeclaration conditionDeclExec; + private final ICPPExecution bodyExec; + + public ExecWhile(ICPPEvaluation conditionExprEval, ExecSimpleDeclaration conditionDeclExec, ICPPExecution bodyExec) { + this.conditionExprEval = conditionExprEval; + this.conditionDeclExec = conditionDeclExec; + this.bodyExec = bodyExec; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + while (conditionSatisfied(record, context)) { + if (context.getStepsPerformed() >= ConstexprEvaluationContext.MAX_CONSTEXPR_EVALUATION_STEPS) { + return ExecIncomplete.INSTANCE; + } + + ICPPExecution result = EvalUtil.executeStatement(bodyExec, record, context); + if(result instanceof ExecReturn) { + return result; + } else if(result instanceof ExecBreak) { + break; + } else if(result instanceof ExecContinue) { + continue; + } + } + return null; + } + + private boolean conditionSatisfied(ActivationRecord record, ConstexprEvaluationContext context) { + if(conditionExprEval != null) { + return EvalUtil.conditionExprSatisfied(conditionExprEval, record, context); + } else if(conditionDeclExec != null) { + return EvalUtil.conditionDeclSatisfied(conditionDeclExec, record, context); + } + return false; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + ICPPEvaluation newConditionExprEval = conditionExprEval != null ? conditionExprEval.instantiate(context, maxDepth) : null; + ExecSimpleDeclaration newConditionDeclExec = conditionDeclExec != null ? (ExecSimpleDeclaration)conditionDeclExec.instantiate(context, maxDepth) : null; + ICPPExecution newBodyExec = bodyExec.instantiate(context, maxDepth); + if (newConditionExprEval == conditionExprEval && newConditionDeclExec == conditionDeclExec && newBodyExec == bodyExec) { + return this; + } + return new ExecWhile(newConditionExprEval, newConditionDeclExec, newBodyExec); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_WHILE); + buffer.marshalEvaluation(conditionExprEval, includeValue); + buffer.marshalExecution(conditionDeclExec, includeValue); + buffer.marshalExecution(bodyExec, includeValue); + } + + public static ISerializableExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + ICPPEvaluation conditionExprEval = (ICPPEvaluation)buffer.unmarshalEvaluation(); + ExecSimpleDeclaration conditionDeclExec = (ExecSimpleDeclaration)buffer.unmarshalExecution(); + ICPPExecution bodyExec = (ICPPExecution)buffer.unmarshalExecution(); + return new ExecWhile(conditionExprEval, conditionDeclExec, bodyExec); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/InitializerListType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/InitializerListType.java index b114f7e4884..8fc86cd4242 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/InitializerListType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/InitializerListType.java @@ -11,11 +11,14 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.core.runtime.CoreException; /** * Wrapper for initializer lists to allow for participation in the overload resolution. */ -class InitializerListType implements IType { +public class InitializerListType implements IType, ISerializableType { private final EvalInitList fInitializerList; public InitializerListType(EvalInitList exprEvalInitList) { @@ -40,4 +43,20 @@ class InitializerListType implements IType { return null; } } + + @Override + public String toString() { + return "InitializerListType"; //$NON-NLS-1$ + } + + @Override + public void marshal(ITypeMarshalBuffer buffer) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.INITIALIZER_LIST_TYPE); + buffer.marshalEvaluation(fInitializerList, true); + } + + public static IType unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + EvalInitList evalInitList = (EvalInitList)buffer.unmarshalEvaluation(); + return new InitializerListType(evalInitList); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index a902d1254d3..a81b8d7eaa9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -55,7 +55,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldDesignator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; @@ -76,6 +75,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluationOwner; /** * Context data for IASTName lookup @@ -524,7 +524,7 @@ public class LookupData extends ScopeLookupData { public void setFunctionArguments(boolean containsImpliedObject, IASTInitializerClause... exprs) { ICPPEvaluation[] evals= new ICPPEvaluation[exprs.length]; for (int i = 0; i < evals.length; i++) { - evals[i]= ((ICPPASTInitializerClause) exprs[i]).getEvaluation(); + evals[i]= ((ICPPEvaluationOwner) exprs[i]).getEvaluation(); } setFunctionArguments(containsImpliedObject, evals); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java index 55b7bdcfb1a..b05751d613d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java @@ -72,7 +72,8 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectSet; import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; @@ -82,6 +83,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluationOwner; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; import org.eclipse.cdt.internal.core.index.IIndexScope; @@ -785,7 +787,7 @@ public class SemanticUtil { for (IEnumerator enumerator : enumerators) { IValue value = enumerator.getValue(); if (value != null) { - Long val = value.numericalValue(); + Number val = value.numberValue(); if (val != null) { long v = val.longValue(); if (v > maxValue) { @@ -803,7 +805,7 @@ public class SemanticUtil { for (IEnumerator enumerator : enumerators) { IValue value = enumerator.getValue(); if (value != null) { - Long val = value.numericalValue(); + Number val = value.numberValue(); if (val != null) { long v = val.longValue(); if (v < minValue) { @@ -845,14 +847,59 @@ public class SemanticUtil { ICPPASTInitializerList list= (ICPPASTInitializerList) init; switch (list.getSize()) { case 0: - return Value.create(0); + return IntegralValue.create(0); case 1: clause= list.getClauses()[0]; + break; + default: + return ((ICPPEvaluationOwner) init).getEvaluation().getValue(init); + } } if (clause instanceof IASTExpression) { - return Value.create((IASTExpression) clause); + return ValueFactory.create((IASTExpression) clause); } - return Value.UNKNOWN; + + if (clause instanceof ICPPASTInitializerList) { + return ((ICPPEvaluationOwner) clause).getEvaluation().getValue(clause); + } + return IntegralValue.UNKNOWN; + } + + /** + * Returns whether a type is const or a reference to a const type. + * + * @param type the type to be checked + * @return true if the type is const, otherwise false + */ + public static boolean isConst(IType type) { + if(type instanceof ICPPReferenceType) { + ICPPReferenceType refType = (ICPPReferenceType)type; + return isConst(refType.getType()); + } else if(type instanceof CPPQualifierType) { + CPPQualifierType qualifierType = (CPPQualifierType)type; + return qualifierType.isConst(); + } + return false; + } + + static IType[] addImplicitParameterType(IType[] types, ICPPMethod m) { + IType t= CPPSemantics.getImplicitParameterType(m); + return concatTypes(t, types); + } + + static IType[] concatTypes(final IType t, IType[] types) { + IType[] result= new IType[types.length+1]; + result[0]= t; + System.arraycopy(types, 0, result, 1, types.length); + return result; + } + + public static IType[] getParameterTypesIncludingImplicitThis(ICPPFunction function) { + IType[] result = function.getType().getParameterTypes(); + if (function instanceof ICPPMethod) { + result = addImplicitParameterType(result, (ICPPMethod) function); + } + return result; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SignatureBuilder.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SignatureBuilder.java index 684dbec2302..1511a0dc3ff 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SignatureBuilder.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SignatureBuilder.java @@ -19,9 +19,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.core.runtime.CoreException; class SignatureBuilder implements ITypeMarshalBuffer { @@ -90,11 +90,20 @@ class SignatureBuilder implements ITypeMarshalBuffer { eval.marshal(this, includeValues); } } + + @Override + public void marshalExecution(ISerializableExecution exec, boolean includeValue) throws CoreException { + if (exec == null) { + putShort(NULL_TYPE); + } else { + exec.marshal(this, includeValue); + } + } @Override public void marshalValue(IValue value) throws CoreException { - if (value instanceof Value) { - ((Value) value).marshal(this); + if (value != null) { + value.marshal(this); } else { putShort(NULL_TYPE); } @@ -167,6 +176,11 @@ class SignatureBuilder implements ITypeMarshalBuffer { public ISerializableEvaluation unmarshalEvaluation() throws CoreException { throw new UnsupportedOperationException(); } + + @Override + public ISerializableExecution unmarshalExecution() throws CoreException { + throw new UnsupportedOperationException(); + } @Override public IValue unmarshalValue() throws CoreException { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java index c5a4eb7b71e..710b0090da7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java @@ -60,7 +60,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; @@ -208,7 +208,7 @@ public class TemplateArgumentDeduction { // Template-argument deduced from an array bound may be of any integral // type. if (type2 instanceof TypeOfValueDeducedFromArraySize && isIntegralType(type1)) { - IValue value = isBooleanType(type1) ? Value.create(true) : arg.getNonTypeValue(); + IValue value = isBooleanType(type1) ? IntegralValue.create(true) : arg.getNonTypeValue(); arg = new CPPTemplateNonTypeArgument(value, type1); deduct.fDeducedArgs.put(tpar, arg); } else if (!type1.isSameType(type2)) { @@ -819,8 +819,8 @@ public class TemplateArgumentDeduction { if (p.isNonTypeValue()) { IValue tval= p.getNonTypeValue(); - if (Value.referencesTemplateParameter(tval)) { - int parId= Value.isTemplateParameter(tval); + if (IntegralValue.referencesTemplateParameter(tval)) { + int parId= IntegralValue.isTemplateParameter(tval); if (parId >= 0) { ICPPTemplateArgument old= fDeducedArgs.getArgument(parId, fPackOffset); if (old == null) { @@ -898,7 +898,7 @@ public class TemplateArgumentDeduction { if (as == null || ps == null) return false; - int parID= Value.isTemplateParameter(ps); + int parID= IntegralValue.isTemplateParameter(ps); if (parID >= 0) { ICPPTemplateArgument old= fDeducedArgs.getArgument(parID, fPackOffset); if (old == null) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeOfUnknownMember.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeOfUnknownMember.java index 5f9fcbbe07b..c0048b7c4da 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeOfUnknownMember.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeOfUnknownMember.java @@ -48,7 +48,7 @@ public class TypeOfUnknownMember implements ICPPUnknownType, ISerializableType { public static IType unmarshal(IIndexFragment fragment, short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { short firstBytesForMember = buffer.getShort(); if ((firstBytesForMember & ITypeMarshalBuffer.KIND_MASK) != ITypeMarshalBuffer.UNKNOWN_MEMBER) - throw new CoreException(CCorePlugin.createStatus("Expected an unknown memebr, first bytes=" + firstBytesForMember)); //$NON-NLS-1$; + throw new CoreException(CCorePlugin.createStatus("Expected an unknown memebr, first bytes=" + firstBytesForMember)); //$NON-NLS-1$ return new TypeOfUnknownMember((CPPUnknownMember) CPPUnknownMember.unmarshal(fragment, firstBytesForMember, buffer)); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java index 504c3565a58..319420d3a4d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java @@ -20,6 +20,7 @@ import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; @@ -34,9 +35,12 @@ import org.eclipse.cdt.core.dom.ast.cpp.SemanticQueries; import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitConstructor; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnaryTypeTransformation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper.MethodKind; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalFunction; /** * A collection of static methods for determining type traits. @@ -57,6 +61,57 @@ public class TypeTraits { private TypeTraits() {} + + + public static boolean isDefaultedMethod(ICPPMethod method) { + if(method instanceof ICPPInternalFunction) { + ICPPInternalFunction internalFunc = (ICPPInternalFunction)method; + IASTNode definition = internalFunc.getDefinition(); + ICPPASTFunctionDefinition functionDefinition = CPPFunction.getFunctionDefinition(definition); + if(functionDefinition != null) { + return functionDefinition.isDefaulted(); + } + } + return false; + } + + + /** + * From $3.9 / 10: + * A type is a literal type if it is: + * [...] + * - a possibly cv-qualified class type that has all the following properties: + * - it has a trivial destructor + * - it is an aggregate type or has at least one constexpr constructor or constructor template that is not a + * copy or move constructor, and + * - all of its non-static data members and base classes are of non-volatile literal types + * TODO: The last property isn't being checked. + */ + public static boolean isLiteralClass(ICPPClassType classType, IASTNode point) { + if(!hasTrivialDestructor(classType, point)) { + return false; + } + + if(isAggregateClass(classType, point)) { + return true; + } + + ICPPConstructor[] ctors = ClassTypeHelper.getConstructors(classType, point); + for(ICPPConstructor ctor : ctors) { + MethodKind methodKind = ClassTypeHelper.getMethodKind(classType, ctor); + if(methodKind == MethodKind.COPY_CTOR || methodKind == MethodKind.MOVE_CTOR) { + continue; + } + + // implicit constructors are automatically constexpr when the class is a literal type + if(ctor instanceof CPPImplicitConstructor || ctor.isConstexpr()) { + return true; + } + } + + return false; + } + /** * C++11: 9-6 */ @@ -314,7 +369,7 @@ public class TypeTraits { * Returns {@code true} if and only if the given class has a trivial destructor. * A destructor is trivial if: *
    - *
  • it is implicitly defined by the compiler, and
  • + *
  • it is implicitly defined by the compiler or defaulted, and
  • *
  • every direct base class has trivial destructor, and
  • *
  • for every nonstatic data member that has class type or array of class type, that type * has trivial destructor.
  • @@ -326,10 +381,10 @@ public class TypeTraits { */ public static boolean hasTrivialDestructor(ICPPClassType classType, IASTNode point) { for (ICPPMethod method : ClassTypeHelper.getDeclaredMethods(classType, point)) { - if (method.isDestructor()) + if (method.isDestructor() && !isDefaultedMethod(method)) return false; } - for (ICPPClassType baseClass : ClassTypeHelper.getAllBases(classType, null)) { + for (ICPPClassType baseClass : ClassTypeHelper.getAllBases(classType, point)) { if (!classType.isSameType(baseClass) && !hasTrivialDestructor(baseClass, point)) return false; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java index 31fcb5df29d..def308cb67a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java @@ -65,7 +65,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableTemplatePartialSpecializatio import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexMacroContainer; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPAliasTemplateInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; @@ -89,7 +89,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinary; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinaryTypeId; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalComma; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalCompound; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalCompoundStatementExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalConditional; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFunctionCall; @@ -332,12 +332,12 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { e= new EvalComma(a2, compositeTemplateDefinition); return e; } - if (eval instanceof EvalCompound) { - EvalCompound e= (EvalCompound) eval; + if (eval instanceof EvalCompoundStatementExpression) { + EvalCompoundStatementExpression e= (EvalCompoundStatementExpression) eval; ICPPEvaluation a = e.getLastEvaluation(); ICPPEvaluation a2 = getCompositeEvaluation(a); if (a != a2 || templateDefinition != compositeTemplateDefinition) - e= new EvalCompound(a2, compositeTemplateDefinition); + e= new EvalCompoundStatementExpression(a2, compositeTemplateDefinition); return e; } if (eval instanceof EvalConditional) { @@ -367,7 +367,7 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { ICPPEvaluation[] a = e.getArguments(); ICPPEvaluation[] a2 = getCompositeEvaluationArray(a); if (a != a2 || templateDefinition != compositeTemplateDefinition) - e= new EvalFunctionCall(a2, compositeTemplateDefinition); + e= new EvalFunctionCall(a2, null, compositeTemplateDefinition); return e; } if (eval instanceof EvalFunctionSet) { @@ -419,13 +419,19 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { EvalMemberAccess e= (EvalMemberAccess) eval; IType a = e.getOwnerType(); IBinding b = e.getMember(); + ICPPEvaluation c = e.getOwnerEval(); IType a2= getCompositeType(a); IBinding b2= b; + ICPPEvaluation c2 = c; if (b instanceof IIndexFragmentBinding) { b2= getCompositeBinding((IIndexFragmentBinding) b); } + if (c != null) { + c2 = getCompositeEvaluation(c); + } if (a != a2 || b != b2 || templateDefinition != compositeTemplateDefinition) - e= new EvalMemberAccess(a2, e.getOwnerValueCategory(), b2, e.isPointerDeref(), compositeTemplateDefinition); + e= new EvalMemberAccess(a2, e.getOwnerValueCategory(), b2, c2, e.isPointerDeref(), + compositeTemplateDefinition); return e; } if (eval instanceof EvalParameterPack) { @@ -443,7 +449,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { IType a2= getCompositeType(a); ICPPEvaluation[] b2 = getCompositeEvaluationArray(b); if (a != a2 || b != b2 || templateDefinition != compositeTemplateDefinition) - e= new EvalTypeId(a2, compositeTemplateDefinition, b2); + e= new EvalTypeId(a2, compositeTemplateDefinition, e.representsNewExpression(), + e.usesBracedInitList(), b2); return e; } if (eval instanceof EvalUnary) { @@ -513,7 +520,7 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { return v; eval = getCompositeEvaluation(eval); - return Value.fromInternalRepresentation(eval); + return IntegralValue.fromInternalRepresentation(eval); } private ICPPNamespace[] getNamespaces(IBinding rbinding) throws CoreException { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructor.java index 0bc56b234ba..1106b95c29d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructor.java @@ -10,12 +10,19 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.index.composite.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; class CompositeCPPConstructor extends CompositeCPPMethod implements ICPPConstructor { public CompositeCPPConstructor(ICompositesFactory cf, ICPPFunction rbinding) { super(cf, rbinding); } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return ((ICPPConstructor) rbinding).getConstructorChainExecution(point); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorInstance.java index 9aa4982cc59..059c7876626 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorInstance.java @@ -10,11 +10,18 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.index.composite.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; public class CompositeCPPConstructorInstance extends CompositeCPPMethodInstance implements ICPPConstructor { public CompositeCPPConstructorInstance(ICompositesFactory cf, ICPPConstructor rbinding) { super(cf, rbinding); } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return ((ICPPConstructor) rbinding).getConstructorChainExecution(point); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorSpecialization.java index 45900be3821..37baee4e9b5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorSpecialization.java @@ -10,7 +10,9 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.index.composite.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; public class CompositeCPPConstructorSpecialization extends CompositeCPPMethodSpecialization implements @@ -18,5 +20,10 @@ public class CompositeCPPConstructorSpecialization extends CompositeCPPMethodSpe public CompositeCPPConstructorSpecialization(ICompositesFactory cf, ICPPConstructor cons) { super(cf, cons); - } + } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return ((ICPPConstructor) rbinding).getConstructorChainExecution(point); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorTemplate.java index 46a011bf422..982c7fc6807 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorTemplate.java @@ -10,7 +10,9 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.index.composite.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; public class CompositeCPPConstructorTemplate extends CompositeCPPMethodTemplate implements ICPPConstructor { @@ -18,4 +20,9 @@ public class CompositeCPPConstructorTemplate extends CompositeCPPMethodTemplate public CompositeCPPConstructorTemplate(ICompositesFactory cf, ICPPConstructor rbinding) { super(cf, rbinding); } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return ((ICPPConstructor) rbinding).getConstructorChainExecution(point); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorTemplateSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorTemplateSpecialization.java index 4c06fc10017..8d5d65a35ae 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorTemplateSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPConstructorTemplateSpecialization.java @@ -10,8 +10,10 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.index.composite.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; public class CompositeCPPConstructorTemplateSpecialization @@ -22,4 +24,9 @@ public class CompositeCPPConstructorTemplateSpecialization ICPPFunction ft) { super(cf, ft); } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + return ((ICPPConstructor) rbinding).getConstructorChainExecution(point); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPField.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPField.java index 971c390abee..7848f1157c9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPField.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPField.java @@ -39,4 +39,9 @@ class CompositeCPPField extends CompositeCPPVariable implements ICPPField { IBinding preresult = ((IField)rbinding).getCompositeTypeOwner(); return (ICompositeType) cf.getCompositeBinding((IIndexFragmentBinding) preresult); } + + @Override + public byte getFieldPosition() { + return ((ICPPField)rbinding).getFieldPosition(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldInstance.java index 2e926a2fc75..b0582c04e1b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldInstance.java @@ -39,4 +39,9 @@ public class CompositeCPPFieldInstance extends CompositeCPPVariableInstance impl return (ICPPClassType) cf.getCompositeBinding( (IIndexFragmentBinding) ((ICPPField) rbinding).getClassOwner()); } + + @Override + public byte getFieldPosition() { + return ((ICPPField)rbinding).getFieldPosition(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldTemplate.java index 76f58ead6aa..41e41ec7dbb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldTemplate.java @@ -40,4 +40,8 @@ public class CompositeCPPFieldTemplate extends CompositeCPPVariableTemplate impl (IIndexFragmentBinding) ((ICPPField)rbinding).getClassOwner()); } + @Override + public byte getFieldPosition() { + return ((ICPPField) rbinding).getFieldPosition(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldTemplatePartialSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldTemplatePartialSpecialization.java index e7f0da437f6..d08fca99766 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldTemplatePartialSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFieldTemplatePartialSpecialization.java @@ -41,4 +41,9 @@ public class CompositeCPPFieldTemplatePartialSpecialization return (ICPPClassType) cf.getCompositeBinding( (IIndexFragmentBinding) ((ICPPField) rbinding).getClassOwner()); } + + @Override + public byte getFieldPosition() { + return ((ICPPField) rbinding).getFieldPosition(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java index fc081a28eb1..21afb13c28b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java @@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPComputableFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; @@ -143,4 +144,9 @@ class CompositeCPPFunction extends CompositeCPPBinding implements ICPPFunction, public ICPPEvaluation getReturnExpression(IASTNode point) { return CPPFunction.getReturnExpression((ICPPFunction) rbinding, point); } + + @Override + public ICPPExecution getFunctionBodyExecution(IASTNode point) { + return CPPFunction.getFunctionBodyExecution((ICPPFunction) rbinding, point); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index c8a8b9547e1..5646d45e0cc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -270,11 +270,14 @@ public class PDOM extends PlatformObject implements IPDOM { * * CDT 9.0 development (versions not supported on the 8.8.x branch) * 200.0 - Added PDOMCPPAliasTemplateInstance, bug 486915. - * 201.0 - PDOMCPPBase stores a CPPParameterPackType for pack expansions, bug 487703. + * 201.0 - PDOMCPPBase stores a CPPParameterPackType for pack expansions, bug 487703. <> + * + * CDT 9.2 development (versions not supported on the 9.0.x branch) + * 202.0 - C++14 constexpr evaluation, bug 490475. */ - private static final int MIN_SUPPORTED_VERSION= version(201, 0); - private static final int MAX_SUPPORTED_VERSION= version(201, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(201, 0); + private static final int MIN_SUPPORTED_VERSION= version(202, 0); + private static final int MAX_SUPPORTED_VERSION= version(202, Short.MAX_VALUE); + private static final int DEFAULT_VERSION = version(202, 0); private static int version(int major, int minor) { return (major << 16) + minor; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java index ca82836f2db..7650c895db4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java @@ -81,6 +81,7 @@ public class Database { public static final int TYPE_SIZE = 2 + PTR_SIZE; // size of a type in the database in bytes public static final int VALUE_SIZE = 1 + PTR_SIZE; // size of a value in the database in bytes public static final int EVALUATION_SIZE = TYPE_SIZE; // size of an evaluation in the database in bytes + public static final int EXECUTION_SIZE = TYPE_SIZE; // size of an execution in the database in bytes public static final int ARGUMENT_SIZE = TYPE_SIZE; // size of a template argument in the database in bytes public static final long MAX_DB_SIZE= ((long) 1 << (Integer.SIZE + BLOCK_SIZE_DELTA_BITS)); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java index 54c694e6b33..b038cf6744a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java @@ -40,6 +40,7 @@ import org.eclipse.cdt.core.index.IIndexLinkage; import org.eclipse.cdt.core.parser.util.CharArrayMap; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.index.IIndexBindingConstants; @@ -429,6 +430,7 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage public abstract IType unmarshalType(ITypeMarshalBuffer buffer) throws CoreException; public abstract IBinding unmarshalBinding(ITypeMarshalBuffer buffer) throws CoreException; public abstract ISerializableEvaluation unmarshalEvaluation(ITypeMarshalBuffer typeMarshalBuffer) throws CoreException; + public abstract ISerializableExecution unmarshalExecution(ITypeMarshalBuffer typeMarhsalBuffer) throws CoreException; public void storeType(long offset, IType type) throws CoreException { final Database db= getDB(); @@ -691,6 +693,31 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage return null; return buffer.unmarshalEvaluation(); } + + public void storeExecution(long offset, ISerializableExecution exec) throws CoreException { + final Database db = getDB(); + deleteExecution(db, offset); + storeExecution(db, offset, exec); + } + + private void storeExecution(Database db, long offset, ISerializableExecution exec) throws CoreException { + if (exec != null) { + TypeMarshalBuffer bc = new TypeMarshalBuffer(this); + bc.marshalExecution(exec, true); + storeBuffer(db, offset, bc, Database.EXECUTION_SIZE); + } + } + + private void deleteExecution(Database db, long offset) throws CoreException { + deleteSerializedData(db, offset, Database.EXECUTION_SIZE); + } + + public ISerializableExecution loadExecution(long offset) throws CoreException { + TypeMarshalBuffer buffer = loadBuffer(offset, Database.EXECUTION_SIZE); + if (buffer == null) + return null; + return buffer.unmarshalExecution(); + } private TypeMarshalBuffer loadBuffer(long offset, int size) throws CoreException { final Database db= getDB(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/TypeMarshalBuffer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/TypeMarshalBuffer.java index 13525f005c0..a80244583b2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/TypeMarshalBuffer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/TypeMarshalBuffer.java @@ -19,12 +19,16 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; +import org.eclipse.cdt.internal.core.dom.parser.CStringValue; +import org.eclipse.cdt.internal.core.dom.parser.CompositeValue; +import org.eclipse.cdt.internal.core.dom.parser.FloatingPointValue; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; @@ -162,16 +166,30 @@ public final class TypeMarshalBuffer implements ITypeMarshalBuffer { eval.marshal(this, includeValues); } } + + @Override + public void marshalExecution(ISerializableExecution exec, boolean includeValue) throws CoreException { + if (exec == null) { + putShort(NULL_TYPE); + } else { + exec.marshal(this, includeValue); + } + } @Override public ISerializableEvaluation unmarshalEvaluation() throws CoreException { return fLinkage.unmarshalEvaluation(this); } + + @Override + public ISerializableExecution unmarshalExecution() throws CoreException { + return fLinkage.unmarshalExecution(this); + } @Override public void marshalValue(IValue value) throws CoreException { - if (value instanceof Value) { - ((Value) value).marshal(this); + if(value != null) { + value.marshal(this); } else { putShort(NULL_TYPE); } @@ -179,10 +197,20 @@ public final class TypeMarshalBuffer implements ITypeMarshalBuffer { @Override public IValue unmarshalValue() throws CoreException { - if (fPos >= fBuffer.length) - throw unmarshallingError(); - - return Value.unmarshal(this); + short firstBytes= getShort(); + if (firstBytes == TypeMarshalBuffer.NULL_TYPE) + return null; + switch ((firstBytes & ITypeMarshalBuffer.KIND_MASK)) { + case ITypeMarshalBuffer.INTEGRAL_VALUE: + return IntegralValue.unmarshal(firstBytes, this); + case ITypeMarshalBuffer.FLOATING_POINT_VALUE: + return FloatingPointValue.unmarshal(firstBytes, this); + case ITypeMarshalBuffer.C_STRING_VALUE: + return CStringValue.unmarshal(firstBytes, this); + case ITypeMarshalBuffer.COMPOSITE_VALUE: + return CompositeValue.unmarshal(firstBytes, this); + } + throw new CoreException(CCorePlugin.createStatus("Cannot unmarshal a value, first bytes=" + firstBytes)); //$NON-NLS-1$ } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCEnumerator.java index 18d26131553..806ebeb80a9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCEnumerator.java @@ -16,7 +16,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.pdom.db.Database; @@ -59,7 +59,7 @@ class PDOMCEnumerator extends PDOMBinding implements IEnumerator { private void storeValue(final Database db, IEnumerator enumerator) throws CoreException { IValue value= enumerator.getValue(); if (value != null) { - Long val= value.numericalValue(); + Number val= value.numberValue(); db.putInt(record + VALUE, val == null ? -1 : val.intValue()); } } @@ -82,10 +82,10 @@ class PDOMCEnumerator extends PDOMBinding implements IEnumerator { public IValue getValue() { try { int val= getDB().getInt(record + VALUE); - return Value.create(val); + return IntegralValue.create(val); } catch (CoreException e) { CCorePlugin.log(e); } - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java index 9beaf3dad16..0f1d910e471 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java @@ -27,6 +27,7 @@ import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.internal.core.dom.ast.tag.TagManager; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.c.CArrayType; @@ -384,4 +385,10 @@ class PDOMCLinkage extends PDOMLinkage implements IIndexCBindingConstants { throws CoreException { throw new CoreException(CCorePlugin.createStatus("Cannot unmarshal an evaluation, first byte=" + buffer.getByte())); //$NON-NLS-1$ } + + @Override + public ISerializableExecution unmarshalExecution(ITypeMarshalBuffer buffer) + throws CoreException { + throw new CoreException(CCorePlugin.createStatus("Cannot unmarshal an execution, first byte=" + buffer.getByte())); //$NON-NLS-1$ + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java index 054ad7a50b6..e598df2b709 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCVariable.java @@ -19,7 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding; 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.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.c.CVariableReadWriteFlags; import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants; import org.eclipse.cdt.internal.core.pdom.db.Database; @@ -107,7 +107,7 @@ class PDOMCVariable extends PDOMBinding implements IVariable { return getLinkage().loadValue(record + VALUE_OFFSET); } catch (CoreException e) { CCorePlugin.log(e); - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java index b7f8bcd30d9..02fd20bd7d6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java @@ -31,7 +31,6 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ICompositeType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; @@ -43,6 +42,7 @@ import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassScope; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.cdt.internal.core.index.DeclaredBindingsFilter; @@ -164,10 +164,7 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { if (!lookup.isPrefixLookup()) { if (CharArrayUtils.equals(fBinding.getNameCharArray(), nameChars)) { if (CPPClassScope.shallReturnConstructors(lookup.getLookupName(), false)){ - if (fBinding instanceof ICPPClassSpecialization) { - return ((ICPPClassSpecialization) fBinding).getConstructors(lookup.getLookupPoint()); - } - return fBinding.getConstructors(); + return ClassTypeHelper.getConstructors(fBinding, lookup.getLookupPoint()); } return new IBinding[] { getClassNameBinding() }; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java index 72dd802c3ce..85f29b9aade 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java @@ -10,25 +10,43 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; +import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; class PDOMCPPConstructor extends PDOMCPPMethod implements ICPPConstructor { + /** Offset of the constructor chain execution for constexpr constructors. */ + private static final int CONSTRUCTOR_CHAIN = PDOMCPPMethod.RECORD_SIZE; // Database.EXECUTION_SIZE + + /** + * The size in bytes of a PDOMCPPConstructor record in the database. + */ + @SuppressWarnings("hiding") + protected static final int RECORD_SIZE = CONSTRUCTOR_CHAIN + Database.EXECUTION_SIZE; + public PDOMCPPConstructor(PDOMCPPLinkage linkage, PDOMNode parent, ICPPConstructor method, IASTNode point) throws CoreException, DOMException { super(linkage, parent, method, point); + linkage.new ConfigureConstructor(method, this); } public PDOMCPPConstructor(PDOMLinkage linkage, long record) { super(linkage, record); } + + @Override + protected int getRecordSize() { + return RECORD_SIZE; + } @Override public int getNodeType() { @@ -39,4 +57,25 @@ class PDOMCPPConstructor extends PDOMCPPMethod implements ICPPConstructor { public int getAdditionalNameFlags(int standardFlags, IASTName name) { return 0; } + + public void initData(ICPPExecution constructorChain) { + try { + getLinkage().storeExecution(record + CONSTRUCTOR_CHAIN, constructorChain); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + if (!isConstexpr()) + return null; + + try { + return (ICPPExecution) getLinkage().loadExecution(record + CONSTRUCTOR_CHAIN); + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorInstance.java index 112b1d43f65..6f9e287db72 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorInstance.java @@ -10,10 +10,13 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; +import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; @@ -23,21 +26,35 @@ import org.eclipse.core.runtime.CoreException; * @author Bryan Wilkinson */ public class PDOMCPPConstructorInstance extends PDOMCPPMethodInstance implements ICPPConstructor { + /** Offset of the constructor chain execution for constexpr constructors. */ + private static final int CONSTRUCTOR_CHAIN = PDOMCPPMethodInstance.RECORD_SIZE + 0; // Database.EXECUTION_SIZE + /** * The size in bytes of a PDOMCPPConstructorInstance record in the database. */ @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = PDOMCPPMethodInstance.RECORD_SIZE + 0; + protected static final int RECORD_SIZE = CONSTRUCTOR_CHAIN + Database.EXECUTION_SIZE; - public PDOMCPPConstructorInstance(PDOMCPPLinkage linkage, PDOMNode parent, ICPPMethod method, + public PDOMCPPConstructorInstance(PDOMCPPLinkage linkage, PDOMNode parent, ICPPConstructor method, PDOMBinding instantiated, IASTNode point) throws CoreException { super(linkage, parent, method, instantiated, point); + linkage.new ConfigureConstructorInstance(method, this, point); } public PDOMCPPConstructorInstance(PDOMLinkage linkage, long bindingRecord) { super(linkage, bindingRecord); } + public void initData(ICPPExecution constructorChain) { + if (constructorChain == null) + return; + try { + getLinkage().storeExecution(record + CONSTRUCTOR_CHAIN, constructorChain); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + @Override protected int getRecordSize() { return RECORD_SIZE; @@ -47,4 +64,21 @@ public class PDOMCPPConstructorInstance extends PDOMCPPMethodInstance implements public int getNodeType() { return IIndexCPPBindingConstants.CPP_CONSTRUCTOR_INSTANCE; } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + if (!isConstexpr()) + return null; + + try { + ICPPExecution exec = (ICPPExecution) getLinkage().loadExecution(record + CONSTRUCTOR_CHAIN); + if (exec == null) { + exec = CPPTemplates.instantiateConstructorChain(this, point); + } + return exec; + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorSpecialization.java index 5ed1bb2f606..68651c001b7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorSpecialization.java @@ -10,9 +10,13 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; +import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; @@ -22,21 +26,35 @@ import org.eclipse.core.runtime.CoreException; * @author Bryan Wilkinson */ class PDOMCPPConstructorSpecialization extends PDOMCPPMethodSpecialization implements ICPPConstructor { + /** Offset of the constructor chain execution for constexpr constructors. */ + private static final int CONSTRUCTOR_CHAIN = PDOMCPPMethodSpecialization.RECORD_SIZE + 0; // Database.EXECUTION_SIZE + /** * The size in bytes of a PDOMCPPConstructorSpecialization record in the database. */ @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = PDOMCPPMethodSpecialization.RECORD_SIZE + 0; + protected static final int RECORD_SIZE = CONSTRUCTOR_CHAIN + Database.EXECUTION_SIZE; public PDOMCPPConstructorSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, ICPPConstructor constructor, PDOMBinding specialized, IASTNode point) throws CoreException { super(linkage, parent, constructor, specialized, point); + linkage.new ConfigureConstructorSpecialization(constructor, this, point); } public PDOMCPPConstructorSpecialization(PDOMLinkage linkage, long bindingRecord) { super(linkage, bindingRecord); } + public void initData(ICPPExecution constructorChain) { + if (constructorChain == null) + return; + try { + getLinkage().storeExecution(record + CONSTRUCTOR_CHAIN, constructorChain); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + @Override protected int getRecordSize() { return RECORD_SIZE; @@ -46,4 +64,21 @@ class PDOMCPPConstructorSpecialization extends PDOMCPPMethodSpecialization imple public int getNodeType() { return IIndexCPPBindingConstants.CPP_CONSTRUCTOR_SPECIALIZATION; } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + if (!isConstexpr()) + return null; + + try { + ICPPExecution exec = (ICPPExecution) getLinkage().loadExecution(record + CONSTRUCTOR_CHAIN); + if (exec == null) { + exec = CPPTemplates.instantiateConstructorChain(this, point); + } + return exec; + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorTemplate.java index 5494c38b7d1..a346b2c7b1f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorTemplate.java @@ -10,10 +10,13 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; +import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; @@ -23,17 +26,53 @@ import org.eclipse.core.runtime.CoreException; */ class PDOMCPPConstructorTemplate extends PDOMCPPMethodTemplate implements ICPPConstructor { + /** Offset of the constructor chain execution for constexpr constructors. */ + private static final int CONSTRUCTOR_CHAIN = PDOMCPPMethodTemplate.RECORD_SIZE; // Database.EXECUTION_SIZE + + /** + * The size in bytes of a PDOMCPPConstructorTemplate record in the database. + */ + @SuppressWarnings("hiding") + protected static final int RECORD_SIZE = CONSTRUCTOR_CHAIN + Database.EXECUTION_SIZE; + public PDOMCPPConstructorTemplate(PDOMCPPLinkage linkage, PDOMNode parent, ICPPConstructor method, IASTNode point) throws CoreException, DOMException { super(linkage, parent, method, point); + linkage.new ConfigureConstructorTemplate(method, this); } public PDOMCPPConstructorTemplate(PDOMLinkage linkage, long record) { super(linkage, record); } - + + @Override + protected int getRecordSize() { + return RECORD_SIZE; + } + @Override public int getNodeType() { return IIndexCPPBindingConstants.CPP_CONSTRUCTOR_TEMPLATE; } + + public void initData(ICPPExecution constructorChain) { + try { + getLinkage().storeExecution(record + CONSTRUCTOR_CHAIN, constructorChain); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + if (!isConstexpr()) + return null; + + try { + return (ICPPExecution) getLinkage().loadExecution(record + CONSTRUCTOR_CHAIN); + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorTemplateSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorTemplateSpecialization.java index 737bfe0f569..76e39ed039e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorTemplateSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructorTemplateSpecialization.java @@ -10,9 +10,13 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; +import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; @@ -23,19 +27,33 @@ import org.eclipse.core.runtime.CoreException; */ class PDOMCPPConstructorTemplateSpecialization extends PDOMCPPMethodTemplateSpecialization implements ICPPConstructor { + /** Offset of the constructor chain execution for constexpr constructors. */ + private static final int CONSTRUCTOR_CHAIN = PDOMCPPMethodTemplateSpecialization.RECORD_SIZE + 0; // Database.EXECUTION_SIZE + /** The size in bytes of a PDOMCPPConstructorTemplateSpecialization record in the database. */ @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = PDOMCPPMethodTemplateSpecialization.RECORD_SIZE + 0; + protected static final int RECORD_SIZE = CONSTRUCTOR_CHAIN + Database.EXECUTION_SIZE; public PDOMCPPConstructorTemplateSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, ICPPConstructor constructor, PDOMBinding specialized, IASTNode point) throws CoreException { super(linkage, parent, constructor, specialized, point); + linkage.new ConfigureConstructorTemplateSpecialization(constructor, this, point); } public PDOMCPPConstructorTemplateSpecialization(PDOMLinkage linkage, long bindingRecord) { super(linkage, bindingRecord); } + public void initData(ICPPExecution constructorChain) { + if (constructorChain == null) + return; + try { + getLinkage().storeExecution(record + CONSTRUCTOR_CHAIN, constructorChain); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + @Override protected int getRecordSize() { return RECORD_SIZE; @@ -45,4 +63,21 @@ class PDOMCPPConstructorTemplateSpecialization extends PDOMCPPMethodTemplateSpec public int getNodeType() { return IIndexCPPBindingConstants.CPP_CONSTRUCTOR_TEMPLATE_SPECIALIZATION; } + + @Override + public ICPPExecution getConstructorChainExecution(IASTNode point) { + if (!isConstexpr()) + return null; + + try { + ICPPExecution exec = (ICPPExecution) getLinkage().loadExecution(record + CONSTRUCTOR_CHAIN); + if (exec == null) { + exec = CPPTemplates.instantiateConstructorChain(this, point); + } + return exec; + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerator.java index 5ec5b2afb74..a4bb144b0c9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerator.java @@ -19,7 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalEnumerator; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; @@ -100,6 +100,6 @@ class PDOMCPPEnumerator extends PDOMCPPBinding implements IPDOMCPPEnumerator { } catch (CoreException e) { CCorePlugin.log(e); } - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeratorSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeratorSpecialization.java index 46369ba67f4..071a655bcc1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeratorSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeratorSpecialization.java @@ -18,7 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalEnumerator; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; @@ -100,6 +100,6 @@ class PDOMCPPEnumeratorSpecialization extends PDOMCPPSpecialization implements I } catch (CoreException e) { CCorePlugin.log(e); } - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPField.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPField.java index 0e709e7f8bc..5cba435c56e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPField.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPField.java @@ -12,10 +12,13 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ICompositeType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; +import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; @@ -24,15 +27,33 @@ import org.eclipse.core.runtime.CoreException; * @author Doug Schaefer */ class PDOMCPPField extends PDOMCPPVariable implements ICPPField { - + protected static final int FIELD_POSITION_OFFSET = PDOMCPPVariable.RECORD_SIZE; // byte + + @SuppressWarnings("hiding") + protected static final int RECORD_SIZE = FIELD_POSITION_OFFSET + 1; + public PDOMCPPField(PDOMLinkage linkage, PDOMNode parent, ICPPField field, boolean setTypeAndValue) throws CoreException { super(linkage, parent, field, setTypeAndValue); + setFieldPosition(field); } public PDOMCPPField(PDOMLinkage linkage, long bindingRecord) { super(linkage, bindingRecord); } + + @Override + public void update(final PDOMLinkage linkage, IBinding newBinding, IASTNode point) throws CoreException { + super.update(linkage, newBinding, point); + if (newBinding instanceof ICPPField) { + setFieldPosition((ICPPField)newBinding); + } + } + + private void setFieldPosition(ICPPField field) throws CoreException { + final Database db = getDB(); + db.putByte(record + FIELD_POSITION_OFFSET, field.getFieldPosition()); + } @Override protected int getRecordSize() { @@ -86,4 +107,9 @@ class PDOMCPPField extends PDOMCPPVariable implements ICPPField { public ICompositeType getCompositeTypeOwner() { return getClassOwner(); } + + @Override + public byte getFieldPosition() { + return getByte(record + FIELD_POSITION_OFFSET); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldInstance.java index 0b75b3de21c..bd54281d945 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldInstance.java @@ -51,4 +51,9 @@ public class PDOMCPPFieldInstance extends PDOMCPPVariableInstance implements ICP public int getNodeType() { return IIndexCPPBindingConstants.CPP_FIELD_INSTANCE; } + + @Override + public byte getFieldPosition() { + return ((ICPPField)getSpecializedBinding()).getFieldPosition(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java index 1bb94907782..06b0ca0ec3c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java @@ -19,8 +19,8 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; @@ -86,10 +86,10 @@ class PDOMCPPFieldSpecialization extends PDOMCPPSpecialization implements ICPPFi return getLinkage().loadValue(record + VALUE_OFFSET); } catch (CoreException e) { CCorePlugin.log(e); - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } - + @Override public boolean isAuto() { return getField().isAuto(); @@ -129,4 +129,9 @@ class PDOMCPPFieldSpecialization extends PDOMCPPSpecialization implements ICPPFi public boolean isMutable() { return getField().isMutable(); } + + @Override + public byte getFieldPosition() { + return getField().getFieldPosition(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldTemplate.java index 0ca2e705e26..ac4fabfceef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldTemplate.java @@ -14,22 +14,34 @@ package org.eclipse.cdt.internal.core.pdom.dom.cpp; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.ICompositeType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFieldTemplate; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; +import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; public class PDOMCPPFieldTemplate extends PDOMCPPVariableTemplate implements ICPPFieldTemplate { + protected static final int FIELD_POSITION_OFFSET = PDOMCPPVariableTemplate.RECORD_SIZE; // byte + + @SuppressWarnings("hiding") + protected static final int RECORD_SIZE = FIELD_POSITION_OFFSET + 1; public PDOMCPPFieldTemplate(PDOMCPPLinkage linkage, PDOMNode parent, ICPPFieldTemplate template) throws CoreException, DOMException { super(linkage, parent, template); + setFieldPosition(template); } public PDOMCPPFieldTemplate(PDOMLinkage pdomLinkage, long record) { super(pdomLinkage, record); } + + private void setFieldPosition(ICPPField field) throws CoreException { + final Database db = getDB(); + db.putByte(record + FIELD_POSITION_OFFSET, field.getFieldPosition()); + } @Override public int getNodeType() { @@ -50,4 +62,9 @@ public class PDOMCPPFieldTemplate extends PDOMCPPVariableTemplate implements ICP public ICPPClassType getClassOwner() { return (ICPPClassType) getOwner(); } + + @Override + public byte getFieldPosition() { + return getByte(record + FIELD_POSITION_OFFSET); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldTemplatePartialSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldTemplatePartialSpecialization.java index 483317eaa0d..344f99e27ed 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldTemplatePartialSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldTemplatePartialSpecialization.java @@ -73,4 +73,9 @@ public class PDOMCPPFieldTemplatePartialSpecialization extends PDOMCPPVariableTe return null; return new PDOMCPPFieldTemplatePartialSpecialization(getLinkage(), rec); } + + @Override + public byte getFieldPosition() { + return ((ICPPField)getPrimaryTemplate()).getFieldPosition(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java index d4363ca4a55..1cd567165f0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java @@ -28,6 +28,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPComputableFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IndexCPPSignatureUtil; import org.eclipse.cdt.internal.core.pdom.db.Database; @@ -82,11 +83,15 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl /** Offset of the return expression for constexpr functions. */ private static final int RETURN_EXPRESSION = REQUIRED_ARG_COUNT + 2; // Database.EVALUATION_SIZE + + /** Offset of the function body execution for constexpr functions. */ + private static final int FUNCTION_BODY = RETURN_EXPRESSION + Database.EVALUATION_SIZE; // Database.EXECUTION_SIZE + /** * The size in bytes of a PDOMCPPFunction record in the database. */ @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = RETURN_EXPRESSION + Database.EVALUATION_SIZE; + protected static final int RECORD_SIZE = FUNCTION_BODY + Database.EXECUTION_SIZE; private short fAnnotation = -1; private int fRequiredArgCount = -1; @@ -120,12 +125,13 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl } public void initData(ICPPFunctionType ftype, ICPPParameter[] params, IType[] exceptionSpec, - ICPPEvaluation returnExpression) { + ICPPEvaluation returnExpression, ICPPExecution functionBody) { try { setType(ftype); setParameters(params); storeExceptionSpec(exceptionSpec); getLinkage().storeEvaluation(record + RETURN_EXPRESSION, returnExpression); + getLinkage().storeExecution(record + FUNCTION_BODY, functionBody); } catch (CoreException e) { CCorePlugin.log(e); } @@ -427,4 +433,17 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl return null; } } + + @Override + public ICPPExecution getFunctionBodyExecution(IASTNode point) { + if (!isConstexpr()) + return null; + + try { + return (ICPPExecution) getLinkage().loadExecution(record + FUNCTION_BODY); + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java index 41e5a2ebd75..48251bb177a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java @@ -27,6 +27,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPComputableFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; @@ -71,11 +73,15 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization /** Offset of the return expression for constexpr functions. */ private static final int RETURN_EXPRESSION = REQUIRED_ARG_COUNT + 2; // Database.EVALUATION_SIZE + + /** Offset of the function body execution for constexpr functions. */ + private static final int FUNCTION_BODY = RETURN_EXPRESSION + Database.EVALUATION_SIZE; // Database.EXECUTION_SIZE + /** * The size in bytes of a PDOMCPPFunctionSpecialization record in the database. */ @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = RETURN_EXPRESSION + Database.EVALUATION_SIZE; + protected static final int RECORD_SIZE = FUNCTION_BODY + Database.EXECUTION_SIZE; private static final short ANNOT_PARAMETER_PACK = 8; private static final short ANNOT_IS_DELETED = 9; @@ -155,11 +161,12 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization super(linkage, bindingRecord); } - public void initData(ICPPEvaluation returnExpression) { - if (returnExpression == null) + public void initData(ICPPEvaluation returnExpression, ICPPExecution functionBody) { + if (returnExpression == null && functionBody == null) return; try { getLinkage().storeEvaluation(record + RETURN_EXPRESSION, returnExpression); + getLinkage().storeExecution(record + FUNCTION_BODY, functionBody); } catch (CoreException e) { CCorePlugin.log(e); } @@ -345,4 +352,21 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization return null; } } + + @Override + public ICPPExecution getFunctionBodyExecution(IASTNode point) { + if (!isConstexpr()) + return null; + + try { + ICPPExecution exec = (ICPPExecution) getLinkage().loadExecution(record + FUNCTION_BODY); + if (exec == null) { + exec = CPPTemplates.instantiateFunctionBody(this, point); + } + return exec; + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 4d94ecf8c22..349a4b6c1ee 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -50,7 +50,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; @@ -87,12 +86,14 @@ import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.dom.ast.tag.TagManager; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredClassInstance; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitMethod; @@ -107,6 +108,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMember; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalEnumerator; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; @@ -114,8 +116,10 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinary; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinaryTypeId; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalComma; -import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalCompound; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalCompositeAccess; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalCompoundStatementExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalConditional; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalConstructor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFunctionCall; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFunctionSet; @@ -123,9 +127,29 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalID; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalInitList; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalMemberAccess; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalParameterPack; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalPointer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalReference; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnary; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnaryTypeID; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecBreak; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecCase; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecCompoundStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecConstructorChain; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecContinue; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecDeclarationStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecDeclarator; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecDefault; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecDo; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecExpressionStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecFor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecIf; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecRangeBasedFor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecReturn; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSimpleDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSwitch; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecWhile; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.InitializerListType; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeOfDependentExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeOfUnknownMember; import org.eclipse.cdt.internal.core.index.IIndexBindingConstants; @@ -251,6 +275,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { private final ICPPParameter[] fOriginalParameters; private final IType[] fOriginalExceptionSpec; private final ICPPEvaluation fReturnExpression; + private final ICPPExecution fFunctionBody; public ConfigureFunction(ICPPFunction original, PDOMCPPFunction function, IASTNode point) throws DOMException { @@ -259,33 +284,68 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { fOriginalParameters= original.getParameters(); fOriginalExceptionSpec= function.extractExceptionSpec(original); fReturnExpression= CPPFunction.getReturnExpression(original, point); + fFunctionBody = CPPFunction.getFunctionBodyExecution(original, point); postProcesses.add(this); } @Override public void run() { fFunction.initData(fOriginalFunctionType, fOriginalParameters, fOriginalExceptionSpec, - fReturnExpression); + fReturnExpression, fFunctionBody); + } + } + + class ConfigureConstructor implements Runnable { + private final PDOMCPPConstructor fConstructor; + private final ICPPExecution fConstructorChain; + + public ConfigureConstructor(ICPPConstructor original, PDOMCPPConstructor constructor) { + fConstructor = constructor; + fConstructorChain = original.getConstructorChainExecution(null); + postProcesses.add(this); + } + + @Override + public void run() { + fConstructor.initData(fConstructorChain); } } class ConfigureFunctionSpecialization implements Runnable { private final PDOMCPPFunctionSpecialization fSpec; private final ICPPEvaluation fReturnExpression; - - public ConfigureFunctionSpecialization(ICPPFunction original, PDOMCPPFunctionSpecialization spec, - IASTNode point) { + private final ICPPExecution fFunctionBody; + + public ConfigureFunctionSpecialization(ICPPFunction original, PDOMCPPFunctionSpecialization spec, IASTNode point) { fSpec = spec; fReturnExpression = CPPFunction.getReturnExpression(original, point); + fFunctionBody = CPPFunction.getFunctionBodyExecution(original, point); postProcesses.add(this); } @Override public void run() { - fSpec.initData(fReturnExpression); + fSpec.initData(fReturnExpression, fFunctionBody); } } + class ConfigureConstructorSpecialization implements Runnable { + private final PDOMCPPConstructorSpecialization fConstructor; + private final ICPPExecution fConstructorChain; + + public ConfigureConstructorSpecialization(ICPPConstructor original, + PDOMCPPConstructorSpecialization constructor, IASTNode point) { + fConstructor = constructor; + fConstructorChain = original.getConstructorChainExecution(point); + postProcesses.add(this); + } + + @Override + public void run() { + fConstructor.initData(fConstructorChain); + } + } + class ConfigureFunctionInstance implements Runnable { private final PDOMCPPFunctionInstance fInstance; private final ICPPTemplateArgument[] fTemplateArguments; @@ -302,6 +362,23 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } } + class ConfigureConstructorInstance implements Runnable { + private final PDOMCPPConstructorInstance fConstructor; + private final ICPPExecution fConstructorChain; + + public ConfigureConstructorInstance(ICPPConstructor original, PDOMCPPConstructorInstance constructor, + IASTNode point) { + fConstructor = constructor; + fConstructorChain = original.getConstructorChainExecution(point); + postProcesses.add(this); + } + + @Override + public void run() { + fConstructor.initData(fConstructorChain); + } + } + class ConfigureFunctionTemplate implements Runnable { private final PDOMCPPFunctionTemplate fTemplate; private final IPDOMCPPTemplateParameter[] fTemplateParameters; @@ -310,6 +387,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { private final ICPPParameter[] fOriginalParameters; private final IType[] fOriginalExceptionSpec; private final ICPPEvaluation fReturnExpression; + private final ICPPExecution fFunctionBody; public ConfigureFunctionTemplate(ICPPFunctionTemplate original, PDOMCPPFunctionTemplate template, IASTNode point) throws DOMException { @@ -320,6 +398,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { fOriginalParameters= original.getParameters(); fOriginalExceptionSpec= template.extractExceptionSpec(original); fReturnExpression= CPPFunction.getReturnExpression(original, point); + fFunctionBody = CPPFunction.getFunctionBodyExecution(original, point); postProcesses.add(this); } @@ -331,7 +410,40 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { tp.configure(fOriginalTemplateParameters[i]); } fTemplate.initData(fOriginalFunctionType, fOriginalParameters, fOriginalExceptionSpec, - fReturnExpression); + fReturnExpression, fFunctionBody); + } + } + + class ConfigureConstructorTemplate implements Runnable { + private final PDOMCPPConstructorTemplate fConstructor; + private final ICPPExecution fConstructorChain; + + public ConfigureConstructorTemplate(ICPPConstructor original, PDOMCPPConstructorTemplate constructor) { + fConstructor = constructor; + fConstructorChain = original.getConstructorChainExecution(null); + postProcesses.add(this); + } + + @Override + public void run() { + fConstructor.initData(fConstructorChain); + } + } + + class ConfigureConstructorTemplateSpecialization implements Runnable { + private final PDOMCPPConstructorTemplateSpecialization fConstructor; + private final ICPPExecution fConstructorChain; + + public ConfigureConstructorTemplateSpecialization(ICPPConstructor original, + PDOMCPPConstructorTemplateSpecialization constructor, IASTNode point) { + fConstructor = constructor; + fConstructorChain = original.getConstructorChainExecution(point); + postProcesses.add(this); + } + + @Override + public void run() { + fConstructor.initData(fConstructorChain); } } @@ -1035,8 +1147,13 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { */ private final PDOMNode adaptOrAddParent(boolean add, IBinding binding) throws CoreException { IBinding owner= binding.getOwner(); - if (owner instanceof IFunction && !(binding instanceof ICPPTemplateParameter)) { - return null; + if (owner instanceof IFunction) { + boolean isTemplateParameter = binding instanceof ICPPTemplateParameter; + boolean ownerIsConstexprFunc = owner instanceof ICPPFunction && ((ICPPFunction) owner).isConstexpr(); + boolean isVariableOrTypedef = binding instanceof ICPPVariable || binding instanceof ITypedef; + if (!isTemplateParameter && !(ownerIsConstexprFunc && isVariableOrTypedef)) { + return null; + } } if (binding instanceof IIndexBinding) { @@ -1260,12 +1377,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } else if (parentNode instanceof ICPPASTCompositeTypeSpecifier) { IBinding classBinding = name.resolveBinding(); if (classBinding instanceof ICPPClassType) { - ICPPBase[] bases; - if (classBinding instanceof ICPPClassSpecialization) { - bases= ((ICPPClassSpecialization) classBinding).getBases(name); - } else { - bases= ((ICPPClassType) classBinding).getBases(); - } + ICPPBase[] bases = ClassTypeHelper.getBases((ICPPClassType)classBinding, name); if (bases.length > 0) { PDOMBinding pdomBinding = pdomName.getBinding(); if (pdomBinding instanceof PDOMCPPClassType) { @@ -1407,6 +1519,9 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return CPPUnaryTypeTransformation.unmarshal(firstBytes, buffer); case ITypeMarshalBuffer.UNKNOWN_MEMBER_TYPE: return TypeOfUnknownMember.unmarshal(getPDOM(), firstBytes, buffer); + case ITypeMarshalBuffer.INITIALIZER_LIST_TYPE: + return InitializerListType.unmarshal(firstBytes, buffer); + // Don't handle DEFERRED_FUNCTION, because it's never a type. } throw new CoreException(CCorePlugin.createStatus("Cannot unmarshal a type, first bytes=" + firstBytes)); //$NON-NLS-1$ @@ -1422,6 +1537,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return CPPUnknownClassInstance.unmarshal(getPDOM(), firstBytes, buffer); case ITypeMarshalBuffer.DEFERRED_CLASS_INSTANCE: return CPPDeferredClassInstance.unmarshal(getPDOM(), firstBytes, buffer); + case ITypeMarshalBuffer.DEFERRED_FUNCTION: + return CPPDeferredFunction.unmarshal(firstBytes, buffer); } throw new CoreException(CCorePlugin.createStatus("Cannot unmarshal a type, first bytes=" + firstBytes)); //$NON-NLS-1$ @@ -1442,7 +1559,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { case ITypeMarshalBuffer.EVAL_COMMA: return EvalComma.unmarshal(firstBytes, buffer); case ITypeMarshalBuffer.EVAL_COMPOUND: - return EvalCompound.unmarshal(firstBytes, buffer); + return EvalCompoundStatementExpression.unmarshal(firstBytes, buffer); case ITypeMarshalBuffer.EVAL_CONDITIONAL: return EvalConditional.unmarshal(firstBytes, buffer); case ITypeMarshalBuffer.EVAL_FIXED: @@ -1465,7 +1582,59 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return EvalUnary.unmarshal(firstBytes, buffer); case ITypeMarshalBuffer.EVAL_UNARY_TYPE_ID: return EvalUnaryTypeID.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EVAL_CONSTRUCTOR: + return EvalConstructor.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EVAL_REFERENCE: + return EvalReference.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EVAL_POINTER: + return EvalPointer.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EVAL_COMPOSITE_ACCESS: + return EvalCompositeAccess.unmarshal(firstBytes, buffer); } throw new CoreException(CCorePlugin.createStatus("Cannot unmarshal an evaluation, first bytes=" + firstBytes)); //$NON-NLS-1$ } + + @Override + public ISerializableExecution unmarshalExecution(ITypeMarshalBuffer buffer) throws CoreException { + short firstBytes = buffer.getShort(); + if(firstBytes == TypeMarshalBuffer.NULL_TYPE) + return null; + switch((firstBytes & ITypeMarshalBuffer.KIND_MASK)) { + case ITypeMarshalBuffer.EXEC_COMPOUND_STATEMENT: + return ExecCompoundStatement.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_BREAK: + return ExecBreak.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_CASE: + return ExecCase.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_CONTINUE: + return ExecContinue.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_DECLARATION_STATEMENT: + return ExecDeclarationStatement.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_DECLARATOR: + return ExecDeclarator.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_DEFAULT: + return ExecDefault.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_SIMPLE_DECLARATION: + return ExecSimpleDeclaration.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_RETURN: + return ExecReturn.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_EXPRESSION_STATEMENT: + return ExecExpressionStatement.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_IF: + return ExecIf.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_WHILE: + return ExecWhile.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_DO: + return ExecDo.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_FOR: + return ExecFor.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_RANGE_BASED_FOR: + return ExecRangeBasedFor.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_SWITCH: + return ExecSwitch.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.EXEC_CONSTRUCTOR_CHAIN: + return ExecConstructorChain.unmarshal(firstBytes, buffer); + } + throw new CoreException(CCorePlugin.createStatus("Cannot unmarshal an execution, first bytes=" + firstBytes)); //$NON-NLS-1$ + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameter.java index bb7e6ae2c68..5f53ba4766a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameter.java @@ -21,7 +21,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.parser.util.CharArrayUtils; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexScope; @@ -47,7 +47,7 @@ class PDOMCPPParameter extends PDOMNamedNode implements ICPPParameter, IPDOMBind } private final IType fType; - private volatile IValue fDefaultValue = Value.NOT_INITIALIZED; + private volatile IValue fDefaultValue = IntegralValue.NOT_INITIALIZED; public PDOMCPPParameter(PDOMLinkage linkage, long record, IType type) { super(linkage, record); @@ -187,7 +187,7 @@ class PDOMCPPParameter extends PDOMNamedNode implements ICPPParameter, IPDOMBind @Override public IValue getDefaultValue() { - if (fDefaultValue == Value.NOT_INITIALIZED) { + if (fDefaultValue == IntegralValue.NOT_INITIALIZED) { try { fDefaultValue = getLinkage().loadValue(record + DEFAULT_VALUE); } catch (CoreException e) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameterSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameterSpecialization.java index cc1243d6ffd..35eff33bddb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameterSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameterSpecialization.java @@ -21,7 +21,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.IPDOMBinding; @@ -38,7 +38,7 @@ class PDOMCPPParameterSpecialization extends PDOMCPPSpecialization implements IC private static final int RECORD_SIZE = DEFAULT_VALUE + Database.VALUE_SIZE; private final IType fType; - private volatile IValue fDefaultValue = Value.NOT_INITIALIZED; + private volatile IValue fDefaultValue = IntegralValue.NOT_INITIALIZED; public PDOMCPPParameterSpecialization(PDOMLinkage linkage, long record, IType t) { super(linkage, record); @@ -118,7 +118,7 @@ class PDOMCPPParameterSpecialization extends PDOMCPPSpecialization implements IC @Override public IValue getDefaultValue() { - if (fDefaultValue == Value.NOT_INITIALIZED) { + if (fDefaultValue == IntegralValue.NOT_INITIALIZED) { try { fDefaultValue = getLinkage().loadValue(record + DEFAULT_VALUE); } catch (CoreException e) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java index 2556d0a13c9..24169180d4b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariable.java @@ -20,7 +20,7 @@ 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.ICPPVariable; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVariableReadWriteFlags; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.pdom.db.Database; @@ -53,7 +53,7 @@ class PDOMCPPVariable extends PDOMCPPBinding implements ICPPVariable { } private void setValue(Database db, IVariable variable) throws CoreException { - IValue val= variable.getInitialValue(); + IValue val = variable.getInitialValue(); getLinkage().storeValue(record + VALUE_OFFSET, val); } @@ -113,7 +113,7 @@ class PDOMCPPVariable extends PDOMCPPBinding implements ICPPVariable { return getLinkage().loadValue(record + VALUE_OFFSET); } catch (CoreException e) { CCorePlugin.log(e); - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariableInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariableInstance.java index ad8cab8cc58..bca47f6a47e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariableInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPVariableInstance.java @@ -18,8 +18,8 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableInstance; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.IPDOMBinding; @@ -129,7 +129,7 @@ public class PDOMCPPVariableInstance extends PDOMCPPSpecialization implements IC return getLinkage().loadValue(record + VALUE); } catch (CoreException e) { CCorePlugin.log(e); - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java index bd6ee3ac4b1..1c9e249b1ca 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CSourceHover.java @@ -274,7 +274,7 @@ public class CSourceHover extends AbstractCEditorTextHover { */ private String computeSourceForEnumerator(IASTTranslationUnit ast, IEnumerator binding) throws CoreException { - Long numValue = binding.getValue().numericalValue(); + Number numValue = binding.getValue().numberValue(); if (numValue != null) { return numValue.toString(); } else { diff --git a/lrparser/org.eclipse.cdt.core.lrparser/old/org/eclipse/cdt/internal/core/dom/lrparser/c99/bindings/C99Enumerator.java b/lrparser/org.eclipse.cdt.core.lrparser/old/org/eclipse/cdt/internal/core/dom/lrparser/c99/bindings/C99Enumerator.java index a7a75b249e5..121f07ba4fb 100644 --- a/lrparser/org.eclipse.cdt.core.lrparser/old/org/eclipse/cdt/internal/core/dom/lrparser/c99/bindings/C99Enumerator.java +++ b/lrparser/org.eclipse.cdt.core.lrparser/old/org/eclipse/cdt/internal/core/dom/lrparser/c99/bindings/C99Enumerator.java @@ -17,7 +17,7 @@ import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.internal.core.dom.Linkage; -import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.core.runtime.PlatformObject; @SuppressWarnings("restriction") @@ -82,6 +82,6 @@ public class C99Enumerator extends PlatformObject implements IC99Binding, IEnume @Override public IValue getValue() { - return Value.UNKNOWN; + return IntegralValue.UNKNOWN; } } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/ASTUtil.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/ASTUtil.java index e702bbb9baa..92e9829b445 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/ASTUtil.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/ASTUtil.java @@ -37,6 +37,7 @@ import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluationOwner; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.qt.core.index.IQMethod; @@ -141,7 +142,7 @@ public class ASTUtil { return null; ICPPASTInitializerClause cppInit = (ICPPASTInitializerClause) init; - ICPPEvaluation eval = cppInit.getEvaluation(); + ICPPEvaluation eval = ((ICPPEvaluationOwner)cppInit).getEvaluation(); return eval == null ? null : getBaseType(eval.getType(cppInit)); } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QEnum.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QEnum.java index 35f2dd57673..dafa3887fe1 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QEnum.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/index/QEnum.java @@ -52,7 +52,7 @@ public class QEnum implements IQEnum { this.name = enumerator.getName(); IValue val = enumerator.getValue(); - this.ordinal = val == null ? null : val.numericalValue(); + this.ordinal = val == null ? null : val.numberValue().longValue(); } @Override diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QmlTypeRegistration.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QmlTypeRegistration.java index cf6b03db0fe..3035acad0a7 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QmlTypeRegistration.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QmlTypeRegistration.java @@ -83,7 +83,7 @@ public class QmlTypeRegistration extends ASTDelegatedName implements IQtASTName return null; IValue val = args[1].getNonTypeValue(); - return val == null ? null : val.numericalValue(); + return val == null ? null : val.numberValue().longValue(); } public String getUri() { diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMLinkage.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMLinkage.java index 2717ef75f2f..097de0081af 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMLinkage.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/pdom/QtPDOMLinkage.java @@ -18,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableExecution; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.db.Database; @@ -296,4 +297,9 @@ public class QtPDOMLinkage extends PDOMLinkage { public ISerializableEvaluation unmarshalEvaluation(ITypeMarshalBuffer typeMarshalBuffer) throws CoreException { throw new CoreException(Activator.error("Qt Linkage does not marshal evaluations")); //$NON-NLS-1$ } + + @Override + public ISerializableExecution unmarshalExecution(ITypeMarshalBuffer typeMarhsalBuffer) throws CoreException { + throw new CoreException(Activator.error("Qt Linkage does not marshal executions")); //$NON-NLS-1$ + } }