From f938b4d08e59c67309cb0fac1e2bbc8dc1acfa90 Mon Sep 17 00:00:00 2001 From: Hannes Vogt Date: Fri, 8 Mar 2019 23:00:22 +0100 Subject: [PATCH] Bug 545021 - Implement noexcept operator - Adds getNoexceptSpecifier() to ICPPFunctionType, returning the evaluation for the noexcept specifier. - Adds isNoexcept() to ICPPEvaluation, which returns the result of applying the noexcept operator to the evaluation. - Empty throw() specifier is treated as noexcept(true). - Improves EvalTypeID.isConstantExpression() for conversions. Change-Id: I4c6418aea21bb258693b33d956bc3745918f3759 Signed-off-by: Hannes Vogt --- .../core/parser/tests/ast2/AST2CPPTests.java | 213 +++++++++++++++++- .../tests/IndexCPPBindingResolutionTest.java | 8 + .../ast/cpp/ICPPASTFunctionDeclarator.java | 9 + .../core/dom/ast/cpp/ICPPFunctionType.java | 8 + .../dom/parser/GCCBuiltinSymbolProvider.java | 4 +- .../core/dom/parser/ProblemFunctionType.java | 6 + .../core/dom/parser/c/CExternalFunction.java | 2 +- .../parser/cpp/CPPASTFunctionDeclarator.java | 16 ++ .../dom/parser/cpp/CPPASTTranslationUnit.java | 4 +- .../core/dom/parser/cpp/CPPClosureType.java | 15 +- .../dom/parser/cpp/CPPDeferredFunction.java | 2 +- .../core/dom/parser/cpp/CPPFunctionType.java | 20 +- .../core/dom/parser/cpp/CPPUnknownMethod.java | 2 +- .../core/dom/parser/cpp/ICPPEvaluation.java | 6 + .../cpp/semantics/AutoTypeResolver.java | 2 +- .../cpp/semantics/BuiltinOperators.java | 2 +- .../parser/cpp/semantics/CPPEvaluation.java | 5 +- .../parser/cpp/semantics/CPPSemantics.java | 2 +- .../parser/cpp/semantics/CPPTemplates.java | 14 +- .../dom/parser/cpp/semantics/CPPVisitor.java | 13 +- .../dom/parser/cpp/semantics/EvalBinary.java | 14 +- .../cpp/semantics/EvalBinaryTypeId.java | 5 + .../dom/parser/cpp/semantics/EvalBinding.java | 5 + .../dom/parser/cpp/semantics/EvalComma.java | 14 ++ .../cpp/semantics/EvalCompositeAccess.java | 5 + .../EvalCompoundStatementExpression.java | 5 + .../parser/cpp/semantics/EvalConditional.java | 5 + .../parser/cpp/semantics/EvalConstructor.java | 5 + .../dom/parser/cpp/semantics/EvalFixed.java | 5 + .../cpp/semantics/EvalFunctionCall.java | 39 +++- .../parser/cpp/semantics/EvalFunctionSet.java | 6 + .../core/dom/parser/cpp/semantics/EvalID.java | 6 + .../parser/cpp/semantics/EvalInitList.java | 9 + .../cpp/semantics/EvalMemberAccess.java | 5 + .../parser/cpp/semantics/EvalNaryTypeId.java | 5 + .../cpp/semantics/EvalPackExpansion.java | 6 + .../parser/cpp/semantics/EvalReference.java | 6 + .../dom/parser/cpp/semantics/EvalTypeId.java | 26 +++ .../dom/parser/cpp/semantics/EvalUnary.java | 20 +- .../parser/cpp/semantics/EvalUnaryTypeID.java | 5 + .../dom/parser/cpp/semantics/EvalUtil.java | 9 + .../parser/cpp/semantics/SemanticUtil.java | 4 +- .../composite/cpp/CPPCompositesFactory.java | 6 +- .../eclipse/cdt/internal/core/pdom/PDOM.java | 9 +- 44 files changed, 531 insertions(+), 46 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 134cc592ab3..111203a785d 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 @@ -11645,10 +11645,10 @@ public class AST2CPPTests extends AST2CPPTestBase { ICPPFunction waldo3 = helper.assertNonProblem("waldo3"); // constexpr on a function *should not* make its return type const assertSameType(waldo1.getType().getReturnType(), CommonCPPTypes.int_); - assertSameType(waldo2.getType().getReturnType(), - new CPPPointerType(new CPPFunctionType(CommonCPPTypes.int_, new IType[] { CommonCPPTypes.int_ }))); + assertSameType(waldo2.getType().getReturnType(), new CPPPointerType( + new CPPFunctionType(CommonCPPTypes.int_, new IType[] { CommonCPPTypes.int_ }, null))); // constexpr on a method *should not* make the method const - assertSameType(waldo3.getType(), new CPPFunctionType(CommonCPPTypes.int_, new IType[] {})); + assertSameType(waldo3.getType(), new CPPFunctionType(CommonCPPTypes.int_, new IType[] {}, null)); } // void waldo() noexcept; @@ -13135,4 +13135,211 @@ public class AST2CPPTests extends AST2CPPTestBase { parseAndCheckImplicitNameBindings(); } + // int fun(); + // int fun_noexcept() noexcept; + // int fun2(int); + // int fun2_noexcept(int) noexcept; + // constexpr int fun_constexpr() {return 1;} + // int (*fptr)(); + // int (*fptr_noexcept)() noexcept; + // bool condition(); + // + // constexpr bool fun_is_not_noexcept = noexcept(fun()); + // constexpr bool unevaluated_fun_is_noexcept = noexcept(fun); + // constexpr bool fun_noexcept_is_noexcept = noexcept(fun_noexcept()); + // constexpr bool fun2_arg_is_not_noexcept = noexcept(fun2(1)); + // constexpr bool fun2_noexcept_arg_is_noexcept = noexcept(fun2_noexcept(1)); + // constexpr bool fun2_noexcept_arg_not_noexcept_is_not_noexcept = noexcept(fun2_noexcept(fun())); + // constexpr bool fun_constexpr_is_noexcept = noexcept(fun_constexpr()); + // constexpr bool fptr_is_not_noexcept = noexcept(fptr()); + // constexpr bool fptr_noexcept_is_noexcept = noexcept(fptr_noexcept()); + // constexpr bool throw_is_not_noexcept = noexcept(throw fun_noexcept()); + public void testNoexceptOperatorFunctions_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("fun_is_not_noexcept", 0); + helper.assertVariableValue("unevaluated_fun_is_noexcept", 1); + helper.assertVariableValue("fun_noexcept_is_noexcept", 1); + helper.assertVariableValue("fun2_arg_is_not_noexcept", 0); + helper.assertVariableValue("fun2_noexcept_arg_is_noexcept", 1); + helper.assertVariableValue("fun2_noexcept_arg_not_noexcept_is_not_noexcept", 0); + helper.assertVariableValue("fun_constexpr_is_noexcept", 1); + helper.assertVariableValue("fptr_is_not_noexcept", 0); + helper.assertVariableValue("fptr_noexcept_is_noexcept", 1); + helper.assertVariableValue("throw_is_not_noexcept", 0); + } + + // int fun(); + // int fun_noexcept() noexcept; + // bool condition(); + // bool noexcept_condition() noexcept; + // constexpr bool comma_is_noexcept = noexcept(fun_noexcept(), fun_noexcept()); + // constexpr bool comma_is_not_noexcept = noexcept(fun(), fun_noexcept()); + // constexpr bool not_noexcept_conditional = noexcept(noexcept_condition() ? fun() : fun_noexcept()); + // constexpr bool is_noexcept_conditional = noexcept(noexcept_condition() ? fun_noexcept() : fun_noexcept()); + // constexpr bool condition_not_noexcept = noexcept(condition() ? fun_noexcept() : fun_noexcept()); + public void testNoexceptOperatorOperators_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("comma_is_noexcept", 1); + helper.assertVariableValue("comma_is_not_noexcept", 0); + helper.assertVariableValue("not_noexcept_conditional", 0); + helper.assertVariableValue("is_noexcept_conditional", 1); + helper.assertVariableValue("condition_not_noexcept", 0); + } + + // struct aggregate{ + // int a; + // }; + // aggregate agg; + // + // constexpr bool aggregate_init_is_noexcept = noexcept(aggregate{1}); + // constexpr bool aggregate_access_is_noexcept = noexcept(agg.a); + public void testNoexceptOperatorAggregate_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("aggregate_init_is_noexcept", 1); + helper.assertVariableValue("aggregate_access_is_noexcept", 1); + } + + // struct myclass{ + // myclass() noexcept{} + // myclass(int){} + // constexpr myclass(int, int){} + // }; + // constexpr bool ctor_is_noexcept = noexcept(myclass{}); + // constexpr bool ctor_is_not_noexcept = noexcept(myclass{1}); + // constexpr bool constexpr_ctor_is_noexcept = noexcept(myclass{1, 1}); + public void testNoexceptOperatorConstructors_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("ctor_is_noexcept", 1); + helper.assertVariableValue("ctor_is_not_noexcept", 0); + helper.assertVariableValue("constexpr_ctor_is_noexcept", 1); + } + + // struct type { + // int mem(); + // int mem_noexcept() noexcept; + // constexpr int constexpr_mem() {return 1;} + // operator int() noexcept; + // operator int*(); + // }; + // type t; + // int (type::*memptr)(); + // int (type::*memptr_noexcept)() noexcept; + // constexpr bool mem_is_not_noexcept = noexcept(type{}.mem()); + // constexpr bool unevaluated_mem_is_noexcept = noexcept(type{}.mem); + // constexpr bool mem_noexcept_is_noexcept = noexcept(type{}.mem_noexcept()); + // constexpr bool constexpr_mem_is_noexcept = noexcept(type{}.constexpr_mem()); + // constexpr bool memptr_is_not_noexcept = noexcept((type{}.*(memptr))()); + // constexpr bool unevaluated_memptr_is_noexcept = noexcept((type{}.*(memptr))); + // constexpr bool memptr_noexcept_is_noexcept = noexcept((type{}.*(memptr_noexcept))()); + // constexpr bool noexcept_conversion = noexcept(static_cast(t)); + // constexpr bool not_noexcept_conversion = noexcept(static_cast(t)); + // constexpr bool conversion_from_constructor = noexcept(static_cast(type{})); + public void testNoexceptOperatorType_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("mem_is_not_noexcept", 0); + helper.assertVariableValue("unevaluated_mem_is_noexcept", 1); + helper.assertVariableValue("mem_noexcept_is_noexcept", 1); + helper.assertVariableValue("constexpr_mem_is_noexcept", 1); + helper.assertVariableValue("memptr_is_not_noexcept", 0); + // TODO(havogt): needs implementation of [except.spec] p.14 (c++11) noexcept for implicitly declared special member functions + // helper.assertVariableValue("unevaluated_memptr_is_noexcept", 1); + helper.assertVariableValue("memptr_noexcept_is_noexcept", 1); + helper.assertVariableValue("noexcept_conversion", 1); + helper.assertVariableValue("not_noexcept_conversion", 0); + helper.assertVariableValue("conversion_from_constructor", 0); + } + + // template + // int funt(T); + // template + // int funt_noexcept(T) noexcept; + // + // constexpr bool funt_is_not_noexcept = noexcept(funt(1)); + // constexpr bool funt_noexcept_is_noexcept = noexcept(funt_noexcept(1)); + public void testNoexceptOperatorFunctionTemplates_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("funt_is_not_noexcept", 0); + helper.assertVariableValue("funt_noexcept_is_noexcept", 1); + } + + // struct type1{ + // void operator=(int); + // bool operator!(); + // }; + // type1 t1; + // struct type2{ + // void operator=(int) noexcept; + // bool operator!() noexcept; + // }; + // type2 t2; + // constexpr bool binaryop_is_not_noexcept = noexcept(t1 = 1); + // constexpr bool unaryop_is_not_noexcept = noexcept(!t1); + // constexpr bool noexcept_binaryop_is_noexcept = noexcept(t2 = 1); + // constexpr bool noexcept_unaryop_is_noexcept = noexcept(!t2); + public void testNoexceptOperatorOverloadedOperators_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("binaryop_is_not_noexcept", 0); + helper.assertVariableValue("unaryop_is_not_noexcept", 0); + helper.assertVariableValue("noexcept_binaryop_is_noexcept", 1); + helper.assertVariableValue("noexcept_unaryop_is_noexcept", 1); + } + + // void fun(); + // void fun_taking_funptr(void(*ptr)()) noexcept; + // + // constexpr bool is_noexcept = noexcept(fun_taking_funptr(fun)); + public void testNoexceptOperatorNoncalledFunctionPtr_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("is_noexcept", 1); + } + + // void fun() throw(); + // constexpr bool is_noexcept = noexcept(fun()); + public void testNoexceptOperatorEmptyThrow_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("is_noexcept", 1); + } + + // auto closure_noexcept = [](int i) noexcept {return i;}; + // constexpr bool is_noexcept = noexcept(closure_noexcept()); + // auto closure = [](int i) {return i;}; + // constexpr bool is_not_noexcept = noexcept(closure()); + // constexpr bool conversion_is_noexcept = noexcept(static_cast(closure)); + public void testNoexceptOperatorLambda_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("is_noexcept", 1); + helper.assertVariableValue("is_not_noexcept", 0); + helper.assertVariableValue("conversion_is_noexcept", 1); + } + + // template + // void foo() noexcept(B); + // + // constexpr bool is_noexcept = noexcept(foo()); + // constexpr bool is_not_noexcept = noexcept(foo()); + public void testNoexceptOperatorDependentNoexcept_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("is_noexcept", 1); + helper.assertVariableValue("is_not_noexcept", 0); + } + + // struct S { int mem; }; + // S foo(); // could throw + // constexpr bool is_not_noexcept = noexcept(foo().mem); // should be false + public void testNoexceptOperatorOwnerEval_545021() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + helper.assertVariableValue("is_not_noexcept", 0); + } } 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 c90605a1739..5385a977821 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 @@ -2552,4 +2552,12 @@ public class IndexCPPBindingResolutionTest extends IndexBindingResolutionTestBas public void testOOM_529646() throws Exception { checkBindings(); } + + // int foo() noexcept; + + // constexpr bool is_noexcept = noexcept(foo()); + public void testNoexceptOperator_545021() throws Exception { + IVariable isNoexcept = getBindingFromASTName("is_noexcept", 11); + assertEquals(1, isNoexcept.getInitialValue().numberValue().longValue()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java index 3f932df46e5..e2be17585fd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java @@ -21,6 +21,7 @@ import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; /** * C++ adds a few things to function declarators. @@ -154,6 +155,14 @@ public interface ICPPASTFunctionDeclarator extends IASTStandardFunctionDeclarato */ public ICPPASTExpression getNoexceptExpression(); + /** + * Returns the noexcept evaluation, or {@code null} if no noexcept specification is present, or + * or an evaluation representing {@code noexcept(true)} in case of an empty exception specification. + * @since 6.7 + * @noreference This method is not intended to be referenced by clients. + */ + public ICPPEvaluation getNoexceptEvaluation(); + /** * Sets the noexcept expression. * @since 5.5 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunctionType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunctionType.java index 26e7c4eeafd..877b8db8da8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunctionType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunctionType.java @@ -17,6 +17,7 @@ package org.eclipse.cdt.core.dom.ast.cpp; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IPointerType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; /** * @noextend This interface is not intended to be extended by clients. @@ -45,6 +46,13 @@ public interface ICPPFunctionType extends IFunctionType { */ public boolean isRValueReference(); + /** + * Returns the evaluation object for the noexcept specifier or null if there is no noexcept specifier. + * @since 6.7 + * @noreference This method is not intended to be referenced by clients. + */ + public ICPPEvaluation getNoexceptSpecifier(); + /** * Whether the function type takes variable number of arguments. * @since 5.2 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java index 9cdbc3a49fb..bf2469eb5f9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java @@ -494,7 +494,7 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { theParms[i] = fCpp ? new CPPBuiltinParameter(pType) : new CBuiltinParameter(pType); } IType rt = toType(returnType); - IFunctionType ft = fCpp ? new CPPFunctionType(rt, pTypes) : new CFunctionType(rt, pTypes); + IFunctionType ft = fCpp ? new CPPFunctionType(rt, pTypes, null) : new CFunctionType(rt, pTypes); IBinding b = fCpp ? new CPPImplicitFunction(toCharArray(name), fScope, (ICPPFunctionType) ft, (ICPPParameter[]) theParms, @@ -608,7 +608,7 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { } else if (tstr.equals("va_list")) { // Use 'char*(*)()' IType rt = toType("char*"); - t = fCpp ? new CPPPointerType(new CPPFunctionType(rt, IType.EMPTY_TYPE_ARRAY)) + t = fCpp ? new CPPPointerType(new CPPFunctionType(rt, IType.EMPTY_TYPE_ARRAY, null)) : new CPointerType(new CFunctionType(rt, IType.EMPTY_TYPE_ARRAY), 0); } else if (tstr.equals("size_t")) { t = toType("unsigned long"); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemFunctionType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemFunctionType.java index e554b3a5597..09d225dd93e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemFunctionType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemFunctionType.java @@ -18,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; 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; /** @@ -81,4 +82,9 @@ public class ProblemFunctionType extends ProblemType implements ICPPFunctionType public IPointerType getThisType() { return new CPPPointerType(new ProblemType(getID())); } + + @Override + public ICPPEvaluation getNoexceptSpecifier() { + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CExternalFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CExternalFunction.java index 01161731339..f571f74fde5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CExternalFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CExternalFunction.java @@ -43,7 +43,7 @@ public class CExternalFunction extends CFunction implements ICExternalBinding { public IFunctionType getType() { if (type == null) { // Bug 321856: Prevent recursions - type = new CPPFunctionType(VOID_TYPE, IType.EMPTY_TYPE_ARRAY); + type = new CPPFunctionType(VOID_TYPE, IType.EMPTY_TYPE_ARRAY, null); IFunctionType computedType = createType(); if (computedType != null) { type = computedType; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java index f5276b31079..c5a448159c7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java @@ -18,6 +18,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; @@ -31,11 +32,16 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVirtSpecifier.SpecifierKind; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionScope; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; /** * Represents a function declarator. */ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPASTFunctionDeclarator { + public static final ICPPEvaluation NOEXCEPT_TRUE = new EvalFixed(CPPBasicType.BOOLEAN, ValueCategory.PRVALUE, + IntegralValue.create(true)); + private ICPPASTParameterDeclaration[] parameters; private IASTTypeId[] typeIds = NO_EXCEPTION_SPECIFICATION; private ICPPASTExpression noexceptExpression; @@ -388,4 +394,14 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPAS } } } + + @Override + public ICPPEvaluation getNoexceptEvaluation() { + if (getNoexceptExpression() != null) { + return getNoexceptExpression().getEvaluation(); + } else if (getExceptionSpecification() == IASTTypeId.EMPTY_TYPEID_ARRAY) { + return NOEXCEPT_TRUE; + } + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java index 7384b9b380b..437d74f03e4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java @@ -103,7 +103,7 @@ public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPAST IBinding temp = null; IType[] newParms = new IType[1]; newParms[0] = cpp_size_t; - ICPPFunctionType newFunctionType = new CPPFunctionType(cpp_void_p, newParms); + ICPPFunctionType newFunctionType = new CPPFunctionType(cpp_void_p, newParms, null); ICPPParameter[] newTheParms = new ICPPParameter[1]; newTheParms[0] = new CPPBuiltinParameter(newParms[0]); temp = new CPPImplicitFunction(OverloadableOperator.NEW.toCharArray(), theScope, newFunctionType, newTheParms, @@ -120,7 +120,7 @@ public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPAST temp = null; IType[] deleteParms = new IType[1]; deleteParms[0] = cpp_void_p; - ICPPFunctionType deleteFunctionType = new CPPFunctionType(cpp_void, deleteParms); + ICPPFunctionType deleteFunctionType = new CPPFunctionType(cpp_void, deleteParms, null); ICPPParameter[] deleteTheParms = new ICPPParameter[1]; deleteTheParms[0] = new CPPBuiltinParameter(deleteParms[0]); temp = new CPPImplicitFunction(OverloadableOperator.DELETE.toCharArray(), theScope, deleteFunctionType, 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 8d06fab4859..db6b297c23c 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 @@ -115,7 +115,8 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP // Function call operator final IType returnType = getReturnType(); final IType[] parameterTypes = getParameterTypes(); - ft = new CPPFunctionType(returnType, parameterTypes, !isMutable(), false, false, false, false); + ft = new CPPFunctionType(returnType, parameterTypes, getNoexceptEvaluation(), !isMutable(), false, false, false, + false); ICPPParameter[] params = getParameters(); char[] operatorParensName = OverloadableOperator.PAREN.toCharArray(); @@ -139,8 +140,9 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP // Conversion operator if (needConversionOperator) { - final CPPFunctionType conversionTarget = new CPPFunctionType(returnType, parameterTypes); - ft = new CPPFunctionType(conversionTarget, IType.EMPTY_TYPE_ARRAY, true, false, false, false, false); + final CPPFunctionType conversionTarget = new CPPFunctionType(returnType, parameterTypes, null); + ft = new CPPFunctionType(conversionTarget, IType.EMPTY_TYPE_ARRAY, + CPPASTFunctionDeclarator.NOEXCEPT_TRUE /* (CWG DR 1722) */, true, false, false, false, false); // Calling CPPASTConversionName.createName(IType) would try to stringize the type to // construct a name, which is unnecessary work (not to mention prone to recursion with // dependent types). Since the name doesn't matter anyways, just make one up. @@ -258,6 +260,13 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP return fParameterTypes; } + private ICPPEvaluation getNoexceptEvaluation() { + ICPPEvaluation eval = null; + if (fLambdaExpression.getDeclarator() != null) + eval = fLambdaExpression.getDeclarator().getNoexceptEvaluation(); + return eval; + } + public ICPPParameter[] getParameters() { if (fParameters == null) { final IType[] parameterTypes = getParameterTypes(); 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 3a277878e41..cf64816dfbc 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 @@ -36,7 +36,7 @@ import org.eclipse.core.runtime.CoreException; 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); + IType.EMPTY_TYPE_ARRAY, null); /** * Creates a CPPDeferredFunction given a set of overloaded functions diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionType.java index 9d2dae38b38..5629c43e377 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionType.java @@ -37,13 +37,14 @@ public class CPPFunctionType implements ICPPFunctionType, ISerializableType { private final boolean hasRefQualifier; private final boolean isRValueReference; private final boolean takesVarargs; + private final ICPPEvaluation noexceptSpecifier; - public CPPFunctionType(IType returnType, IType[] types) { - this(returnType, types, false, false, false, false, false); + public CPPFunctionType(IType returnType, IType[] types, ICPPEvaluation noexceptSpecifier) { + this(returnType, types, noexceptSpecifier, false, false, false, false, false); } - public CPPFunctionType(IType returnType, IType[] types, boolean isConst, boolean isVolatile, - boolean hasRefQualifier, boolean isRValueReference, boolean takesVarargs) { + public CPPFunctionType(IType returnType, IType[] types, ICPPEvaluation noexceptSpecifier, boolean isConst, + boolean isVolatile, boolean hasRefQualifier, boolean isRValueReference, boolean takesVarargs) { this.returnType = returnType; this.parameters = types; this.isConst = isConst; @@ -51,6 +52,7 @@ public class CPPFunctionType implements ICPPFunctionType, ISerializableType { this.hasRefQualifier = hasRefQualifier; this.isRValueReference = isRValueReference; this.takesVarargs = takesVarargs; + this.noexceptSpecifier = noexceptSpecifier; } @Override @@ -167,6 +169,7 @@ public class CPPFunctionType implements ICPPFunctionType, ISerializableType { for (int i = 0; i < parameters.length; i++) { buffer.marshalType(parameters[i]); } + buffer.marshalEvaluation(noexceptSpecifier, true); } public static IType unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { @@ -176,11 +179,18 @@ public class CPPFunctionType implements ICPPFunctionType, ISerializableType { for (int i = 0; i < pars.length; i++) { pars[i] = buffer.unmarshalType(); } + ICPPEvaluation noexcept = buffer.unmarshalEvaluation(); boolean isConst = (firstBytes & ITypeMarshalBuffer.FLAG1) != 0; boolean takesVarargs = (firstBytes & ITypeMarshalBuffer.FLAG2) != 0; boolean isVolatile = (firstBytes & ITypeMarshalBuffer.FLAG3) != 0; boolean hasRefQualifier = (firstBytes & ITypeMarshalBuffer.FLAG4) != 0; boolean isRValueReference = (firstBytes & ITypeMarshalBuffer.FLAG5) != 0; - return new CPPFunctionType(rt, pars, isConst, isVolatile, hasRefQualifier, isRValueReference, takesVarargs); + return new CPPFunctionType(rt, pars, noexcept, isConst, isVolatile, hasRefQualifier, isRValueReference, + takesVarargs); + } + + @Override + public ICPPEvaluation getNoexceptSpecifier() { + return noexceptSpecifier; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java index 1c0f21daf5e..abe90b7f058 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java @@ -27,7 +27,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemType; */ public class CPPUnknownMethod extends CPPUnknownMember implements ICPPMethod { private static final ICPPFunctionType FUNCTION_TYPE = new CPPFunctionType(ProblemType.UNKNOWN_FOR_EXPRESSION, - IType.EMPTY_TYPE_ARRAY); + IType.EMPTY_TYPE_ARRAY, null); public CPPUnknownMethod(IType owner, char[] name) { super(owner, name); 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 2624aa05e97..a8d959ef281 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 @@ -51,6 +51,12 @@ public interface ICPPEvaluation { */ boolean isConstantExpression(); + /** + * Return the result of the noexcept-operator applied to the expression. + * [expr.unary.noexcept] + */ + boolean isNoexcept(); + /** * Returns {@code true} if this expression is equivalent to 'other' for * declaration matching purposes. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java index 4ca169e751c..8a4bb012a8c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java @@ -41,7 +41,7 @@ class AutoTypeResolver implements ICPPFunctionTemplate { private final CPPFunctionType functionType; public AutoTypeResolver(IType paramType) { - functionType = new CPPFunctionType(new CPPBasicType(Kind.eVoid, 0), new IType[] { paramType }); + functionType = new CPPFunctionType(new CPPBasicType(Kind.eVoid, 0), new IType[] { paramType }, null); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java index 6dcf8df35c3..26276e39bfe 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java @@ -555,7 +555,7 @@ class BuiltinOperators { private void addFunction(IType returnType, IType[] parameterTypes) { ICPPParameter[] parameter = new ICPPParameter[parameterTypes.length]; - ICPPFunctionType functionType = new CPPFunctionType(returnType, parameterTypes); + ICPPFunctionType functionType = new CPPFunctionType(returnType, parameterTypes, null); String sig = ASTTypeUtil.getType(functionType, true); if (fSignatures == null) { fSignatures = new HashSet<>(); 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 7dd48579219..bb631bb9198 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 @@ -172,9 +172,10 @@ public abstract class CPPEvaluation implements ICPPEvaluation { * @param argument the evaluation to convert * @param targetType the type to convert to * @param allowContextualConversion enable/disable explicit contextual conversion + * @param onlyConstexprConversion allow only constexpr conversion operators */ protected static ICPPEvaluation maybeApplyConversion(ICPPEvaluation argument, IType targetType, - boolean allowContextualConversion) { + boolean allowContextualConversion, boolean onlyConstexprConversion) { if (targetType == null) { return argument; } @@ -195,7 +196,7 @@ public abstract class CPPEvaluation implements ICPPEvaluation { targetType, false, allowContextualConversion); ICPPFunction conversion = cost.getUserDefinedConversion(); if (conversion != null) { - if (!conversion.isConstexpr()) { + if (onlyConstexprConversion && !conversion.isConstexpr()) { return EvalFixed.INCOMPLETE; } ICPPEvaluation eval = new EvalMemberAccess(uqType, valueCategory, conversion, argument, false, 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 2b20779a8fc..6728e38cb71 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 @@ -4132,7 +4132,7 @@ public class CPPSemantics { parms[i] = t; theParms[i] = new CPPBuiltinParameter(t); } - ICPPFunctionType functionType = new CPPFunctionType(returnType, parms); + ICPPFunctionType functionType = new CPPFunctionType(returnType, parms, null); return new CPPImplicitFunction(CALL_FUNCTION, scope, functionType, theParms, false, false); } 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 f8703278cc8..5d96ed989a6 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 @@ -1559,7 +1559,10 @@ public class CPPTemplates { IType[] params = instantiateTypes(ps, context); final IType r = ft.getReturnType(); IType ret = instantiateType(r, context); - if (ret == r && params == ps) { + ICPPEvaluation noex = ft.getNoexceptSpecifier(); + ICPPEvaluation noexcept = noex == null ? null + : noex.instantiate(context, IntegralValue.MAX_RECURSION_DEPTH); + if (ret == r && params == ps && noexcept == noex) { return type; } // The parameter types need to be adjusted. @@ -1569,7 +1572,8 @@ public class CPPTemplates { params[i] = CPPVisitor.adjustParameterType(p, true); } } - return new CPPFunctionType(ret, params, ft.isConst(), ft.isVolatile(), ft.hasRefQualifier(), + + return new CPPFunctionType(ret, params, noexcept, ft.isConst(), ft.isVolatile(), ft.hasRefQualifier(), ft.isRValueReference(), ft.takesVarArgs()); } @@ -2609,8 +2613,8 @@ public class CPPTemplates { IType[] parameterTypesWithExplicitArguments = Arrays.copyOf(originalType.getParameterTypes(), nExplicitArgs); return new CPPFunctionType(originalType.getReturnType(), parameterTypesWithExplicitArguments, - originalType.isConst(), originalType.isVolatile(), originalType.hasRefQualifier(), - originalType.isRValueReference(), originalType.takesVarArgs()); + originalType.getNoexceptSpecifier(), originalType.isConst(), originalType.isVolatile(), + originalType.hasRefQualifier(), originalType.isRValueReference(), originalType.takesVarArgs()); } else return originalType; } @@ -2966,7 +2970,7 @@ public class CPPTemplates { Cost cost = Conversions.checkImplicitConversionSequence(p, a, LVALUE, UDCMode.FORBIDDEN, Context.ORDINARY); if (cost == null || !cost.converts()) { ICPPEvaluation eval = arg.getNonTypeEvaluation(); - ICPPEvaluation newEval = CPPEvaluation.maybeApplyConversion(eval, p, false); + ICPPEvaluation newEval = CPPEvaluation.maybeApplyConversion(eval, p, false, true); if (newEval == EvalFixed.INCOMPLETE && newEval != eval) return null; return new CPPTemplateNonTypeArgument(newEval); 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 fd240c4c9d6..bff715b23a8 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 @@ -1899,7 +1899,9 @@ public class CPPVisitor extends ASTQueries { pTypes[i] = pt; } - return new CPPFunctionType(returnType, pTypes, isConst, isVolatile, false, false, false); + return new CPPFunctionType(returnType, pTypes, + null /* TODO(havogt) [except.spec] p.14 (c++11) noexcept for implicitly declared special member functions not implemented */, + isConst, isVolatile, false, false, false); } /** @@ -1946,8 +1948,8 @@ public class CPPVisitor extends ASTQueries { } RefQualifier refQualifier = fnDtor.getRefQualifier(); - CPPFunctionType type = new CPPFunctionType(returnType, pTypes, fnDtor.isConst(), fnDtor.isVolatile(), - refQualifier != null, refQualifier == RefQualifier.RVALUE, fnDtor.takesVarArgs()); + CPPFunctionType type = new CPPFunctionType(returnType, pTypes, fnDtor.getNoexceptEvaluation(), fnDtor.isConst(), + fnDtor.isVolatile(), refQualifier != null, refQualifier == RefQualifier.RVALUE, fnDtor.takesVarArgs()); final IASTDeclarator nested = fnDtor.getNestedDeclarator(); if (nested != null) { return createType(type, nested); @@ -2546,8 +2548,9 @@ public class CPPVisitor extends ASTQueries { // above. IType[] pTypes = createParameterTypes(declarator); RefQualifier refQualifier = declarator.getRefQualifier(); - IType result = new CPPFunctionType(returnType, pTypes, declarator.isConst(), declarator.isVolatile(), - refQualifier != null, refQualifier == RefQualifier.RVALUE, declarator.takesVarArgs()); + IType result = new CPPFunctionType(returnType, pTypes, declarator.getNoexceptEvaluation(), + declarator.isConst(), declarator.isVolatile(), refQualifier != null, + refQualifier == RefQualifier.RVALUE, declarator.takesVarArgs()); final IASTDeclarator nested = declarator.getNestedDeclarator(); if (nested != null) { result = createType(result, nested); 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 3f8522e833c..464e389ed49 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 @@ -184,8 +184,8 @@ public class EvalBinary extends CPPDependentEvaluation { IType[] parameterTypes = SemanticUtil.getParameterTypesIncludingImplicitThis(overload); if (parameterTypes.length >= 2) { boolean allowContextualConversion = operatorAllowsContextualConversion(); - arg1 = maybeApplyConversion(fArg1, parameterTypes[0], allowContextualConversion); - arg2 = maybeApplyConversion(fArg2, parameterTypes[1], allowContextualConversion); + arg1 = maybeApplyConversion(fArg1, parameterTypes[0], allowContextualConversion, true); + arg2 = maybeApplyConversion(fArg2, parameterTypes[1], allowContextualConversion, true); } else { CCorePlugin.log(IStatus.ERROR, "Unexpected overload for binary operator " + fOperator //$NON-NLS-1$ + ": '" + overload.getName() + "'"); //$NON-NLS-1$//$NON-NLS-2$ @@ -611,4 +611,14 @@ public class EvalBinary extends CPPDependentEvaluation { public String toString() { return fArg1.toString() + " " + fArg2.toString(); //$NON-NLS-1$ } + + @Override + public boolean isNoexcept() { + ICPPFunction overload = getOverload(); + if (overload != null) { + if (!EvalUtil.evaluateNoexceptSpecifier(overload.getType().getNoexceptSpecifier())) + return false; + } + return fArg1.isNoexcept() && fArg2.isNoexcept(); + } } 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 46202d4b114..21aff0403ca 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 @@ -167,4 +167,9 @@ public class EvalBinaryTypeId extends CPPDependentEvaluation { public boolean referencesTemplateParameter() { return isValueDependent(); } + + @Override + public boolean isNoexcept() { + return true; + } } 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 bec2013b6f2..2da98771cf1 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 @@ -532,4 +532,9 @@ public class EvalBinding extends CPPDependentEvaluation { public String toString() { return getBinding().toString(); } + + @Override + public boolean isNoexcept() { + return true; + } } 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 3878c76fa59..bc49e2cd3d0 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 @@ -265,4 +265,18 @@ public class EvalComma extends CPPDependentEvaluation { } return false; } + + @Override + public boolean isNoexcept() { + if (getOverloads() != null) + for (ICPPFunction overload : getOverloads()) { + if (overload != null && !EvalUtil.evaluateNoexceptSpecifier(overload.getType().getNoexceptSpecifier())) + return false; + } + for (ICPPEvaluation arg : fArguments) { + if (!arg.isNoexcept()) + return false; + } + return true; + } } 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 index f379bdd3706..f19ee155716 100644 --- 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 @@ -188,4 +188,9 @@ public final class EvalCompositeAccess implements ICPPEvaluation { int elementId = buffer.getInt(); return new EvalCompositeAccess(parent, elementId); } + + @Override + public boolean isNoexcept() { + return parent.isNoexcept(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompoundStatementExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompoundStatementExpression.java index 4aaf284c02b..41b214204f1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompoundStatementExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompoundStatementExpression.java @@ -142,4 +142,9 @@ public class EvalCompoundStatementExpression extends CPPDependentEvaluation { public boolean referencesTemplateParameter() { return fDelegate.referencesTemplateParameter(); } + + @Override + public boolean isNoexcept() { + return fDelegate.isNoexcept(); + } } 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 348eb29da62..3af16b1d397 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 @@ -417,4 +417,9 @@ public class EvalConditional extends CPPDependentEvaluation { || (fPositive != null && fPositive.referencesTemplateParameter()) || fNegative.referencesTemplateParameter(); } + + @Override + public boolean isNoexcept() { + return fCondition.isNoexcept() && fPositive.isNoexcept() && fNegative.isNoexcept(); + } } 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 index 4d6073838ed..c31c059260e 100644 --- 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 @@ -391,4 +391,9 @@ public final class EvalConstructor extends CPPDependentEvaluation { return new EvalConstructor(newType, newConstructor, newArguments, getTemplateDefinition()); } + + @Override + public boolean isNoexcept() { + return EvalUtil.evaluateNoexceptSpecifier(fConstructor.getType().getNoexceptSpecifier()); + } } 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 1eab6725954..8618a1431af 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 @@ -226,4 +226,9 @@ public final class EvalFixed extends CPPEvaluation { public String toString() { return fType.toString() + ": " + fValue.toString(); //$NON-NLS-1$ } + + @Override + public boolean isNoexcept() { + return true; + } } \ 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 6924190c166..47d757faf2f 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 @@ -33,6 +33,7 @@ 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.ICPPFunctionType; 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; @@ -42,6 +43,7 @@ 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.DependentValue; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; 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; @@ -126,7 +128,7 @@ public final class EvalFunctionCall extends CPPDependentEvaluation { } private boolean computeIsConstantExpression() { - return areAllConstantExpressions(fArguments) && isNullOrConstexprFunc(getOverload()); + return areAllConstantExpressions(fArguments) && isNullOrConstexprFunc(resolveFunctionBinding()); } @Override @@ -425,7 +427,7 @@ public final class EvalFunctionCall extends CPPDependentEvaluation { break; } else { if (j < arguments.length) { - ICPPEvaluation argument = maybeApplyConversion(arguments[j++], param.getType(), false); + ICPPEvaluation argument = maybeApplyConversion(arguments[j++], param.getType(), false, true); record.update(param, argument); } else if (param.hasDefaultValue()) { IValue value = param.getDefaultValue(); @@ -495,4 +497,37 @@ public final class EvalFunctionCall extends CPPDependentEvaluation { return null; } } + + ICPPFunctionType resolveFunctionType() { + ICPPFunction function = resolveFunctionBinding(); + if (function != null) { + return function.getType(); + } + IType result = fArguments[0].getType(); + if (result instanceof IPointerType) { + result = ((IPointerType) result).getType(); + } else if (result instanceof CPPClosureType) { + result = ((CPPClosureType) result).getFunctionCallOperator().getType(); + } + if (result instanceof ICPPFunctionType) { + return (ICPPFunctionType) result; + } + return null; + } + + @Override + public boolean isNoexcept() { + ICPPFunctionType fctType = resolveFunctionType(); + if (fctType != null) { + if (!EvalUtil.evaluateNoexceptSpecifier(fctType.getNoexceptSpecifier())) + return false; + } + + for (int i = 1; i < fArguments.length; i++) { + ICPPEvaluation eval = fArguments[i]; + if (!eval.isNoexcept()) + return false; + } + return true; + } } 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 a53201a0d0e..f4f43a1d88e 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 @@ -380,4 +380,10 @@ public class EvalFunctionSet extends CPPDependentEvaluation { public boolean referencesTemplateParameter() { return false; } + + @Override + public boolean isNoexcept() { + assert false; // Shouldn't exist outside of a dependent context + return true; + } } 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 26c0d6c8844..97d5a680415 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 @@ -513,4 +513,10 @@ public class EvalID extends CPPDependentEvaluation { public boolean referencesTemplateParameter() { return fFieldOwner != null && fFieldOwner.referencesTemplateParameter(); } + + @Override + public boolean isNoexcept() { + assert false; // Shouldn't exist outside of a dependent context + return true; + } } 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 dc14b763579..42c5967c869 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 @@ -180,4 +180,13 @@ public class EvalInitList extends CPPDependentEvaluation { } return false; } + + @Override + public boolean isNoexcept() { + for (ICPPEvaluation eval : getClauses()) { + if (!eval.isNoexcept()) + return false; + } + return true; + } } 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 6ae8a86ccd8..8ec8c2a6f52 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 @@ -470,4 +470,9 @@ public class EvalMemberAccess extends CPPDependentEvaluation { public boolean referencesTemplateParameter() { return false; } + + @Override + public boolean isNoexcept() { + return fOwnerEval.isNoexcept(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalNaryTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalNaryTypeId.java index f233936ac35..0b8a0c8bc4a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalNaryTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalNaryTypeId.java @@ -169,4 +169,9 @@ public class EvalNaryTypeId extends CPPDependentEvaluation { IBinding templateDefinition = buffer.unmarshalBinding(); return new EvalNaryTypeId(Operator.values()[op], operands, templateDefinition); } + + @Override + public boolean isNoexcept() { + return true; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalPackExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalPackExpansion.java index 323b6c78755..ed864805cda 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalPackExpansion.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalPackExpansion.java @@ -145,4 +145,10 @@ public class EvalPackExpansion extends CPPDependentEvaluation { IBinding templateDefinition = buffer.unmarshalBinding(); return new EvalPackExpansion(expansionPattern, templateDefinition); } + + @Override + public boolean isNoexcept() { + assert false; // Shouldn't exist outside of a dependent context + return true; + } } \ No newline at end of file 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 index 44a5d3ebe46..5b821d351ea 100644 --- 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 @@ -193,4 +193,10 @@ public class EvalReference extends CPPDependentEvaluation { return new EvalReference(record, referredBinding, templateDefinition); } } + + @Override + public boolean isNoexcept() { + assert false; + return true; + } } 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 fad9747c5c1..1abb5425a0a 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 @@ -250,6 +250,12 @@ public class EvalTypeId extends CPPDependentEvaluation { } private boolean computeIsConstantExpression() { + if (getConstructor() == null && fArguments.length == 1) { + // maybe EvalTypeID represents a conversion + ICPPEvaluation conversionEval = maybeApplyConversion(fArguments[0], fInputType, false, false); + if (!conversionEval.isConstantExpression()) + return false; + } return !fRepresentsNewExpression && areAllConstantExpressions(fArguments) && isNullOrConstexprFunc(getConstructor()); } @@ -477,4 +483,24 @@ public class EvalTypeId extends CPPDependentEvaluation { } return false; } + + @Override + public boolean isNoexcept() { + if (getConstructor() instanceof CPPFunction) { + CPPFunction f = (CPPFunction) getConstructor(); + if (f != AGGREGATE_INITIALIZATION) { + if (!EvalUtil.evaluateNoexceptSpecifier(f.getType().getNoexceptSpecifier())) + return false; + } + } else if (fArguments.length == 1) { + // maybe EvalTypeID represents a conversion + ICPPEvaluation conversionEval = maybeApplyConversion(fArguments[0], fInputType, false, false); + return conversionEval.isNoexcept(); + } + for (ICPPEvaluation arg : fArguments) { + if (!arg.isNoexcept()) + return false; + } + return true; + } } 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 b90f0f92e61..1dde894ea42 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 @@ -313,7 +313,7 @@ public class EvalUnary extends CPPDependentEvaluation { if (parameterTypes.length == 0) return IntegralValue.ERROR; IType targetType = parameterTypes[0]; - arg = maybeApplyConversion(arg, targetType, fOperator == op_not); + arg = maybeApplyConversion(arg, targetType, fOperator == op_not, false); if (!(overload instanceof CPPImplicitFunction)) { if (!overload.isConstexpr()) @@ -334,7 +334,11 @@ public class EvalUnary extends CPPDependentEvaluation { return info == null ? IntegralValue.UNKNOWN : IntegralValue.create(info.alignment); } case op_noexcept: - return IntegralValue.UNKNOWN; // TODO(sprigogin): Implement + // [expr.unary.noexcept] + if (arg.isConstantExpression()) + return IntegralValue.create(true); + else + return IntegralValue.create(arg.isNoexcept()); case op_sizeofParameterPack: IValue opVal = fArgument.getValue(); return IntegralValue.create(opVal.numberOfSubValues()); @@ -523,4 +527,16 @@ public class EvalUnary extends CPPDependentEvaluation { public boolean referencesTemplateParameter() { return fArgument.referencesTemplateParameter(); } + + @Override + public boolean isNoexcept() { + if (fOperator == op_throw) + return false; + ICPPFunction overload = getOverload(); + if (overload != null) { + if (!EvalUtil.evaluateNoexceptSpecifier(overload.getType().getNoexceptSpecifier())) + return false; + } + return fArgument.isNoexcept(); + } } 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 7d91bdeea9d..429ea286340 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 @@ -297,4 +297,9 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { } return EvalFixed.INCOMPLETE; } + + @Override + public boolean isNoexcept() { + return true; + } } 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 index 67ed6a80cf2..3e668dce2ef 100644 --- 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 @@ -203,4 +203,13 @@ public class EvalUtil { public static boolean isDefaultConstructor(ICPPConstructor constructor) { return constructor.getRequiredArgumentCount() == 0; } + + public static boolean evaluateNoexceptSpecifier(ICPPEvaluation noexceptSpecifier) { + if (noexceptSpecifier != null && noexceptSpecifier.getValue() instanceof IntegralValue) { + IntegralValue v = (IntegralValue) noexceptSpecifier.getValue(); + if (v.numberValue() != null) + return v.numberValue().longValue() == 1; + } + 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/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java index 902d49cf82d..eaca924d507 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 @@ -361,8 +361,8 @@ public class SemanticUtil { if (ret == r && params == ps) { return type; } - return new CPPFunctionType(ret, params, ft.isConst(), ft.isVolatile(), ft.hasRefQualifier(), - ft.isRValueReference(), ft.takesVarArgs()); + return new CPPFunctionType(ret, params, ft.getNoexceptSpecifier(), ft.isConst(), ft.isVolatile(), + ft.hasRefQualifier(), ft.isRValueReference(), ft.takesVarArgs()); } if (type instanceof ITypedef) { 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 e13781e11f4..9f0eb61f80a 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 @@ -178,8 +178,10 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { IType r2 = getCompositeType(r); IType[] p = ft.getParameterTypes(); IType[] p2 = getCompositeTypes(p); - if (r != r2 || p != p2) { - return new CPPFunctionType(r2, p2, ft.isConst(), ft.isVolatile(), ft.hasRefQualifier(), + ICPPEvaluation n = ft.getNoexceptSpecifier(); + ICPPEvaluation n2 = getCompositeEvaluation(n); + if (r != r2 || p != p2 || n != n2) { + return new CPPFunctionType(r2, p2, n2, ft.isConst(), ft.isVolatile(), ft.hasRefQualifier(), ft.isRValueReference(), ft.takesVarArgs()); } return ft; 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 3cdb615386e..f395ea5d343 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 @@ -296,10 +296,13 @@ public class PDOM extends PlatformObject implements IPDOM { * CDT 9.5 development (version not supported on the 9.4.x branch) * 212.0 - C++ constexpr if and if init-statement evaluation * 213.0 - C++ switch init-statement evaluation + * + * CDT 9.8 development (version not supported on the 9.7.x branch) + * 214.0 - Noexcept specifier in CPPFunctionType, bug 545021 */ - private static final int MIN_SUPPORTED_VERSION = version(213, 0); - private static final int MAX_SUPPORTED_VERSION = version(213, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(213, 0); + private static final int MIN_SUPPORTED_VERSION = version(214, 0); + private static final int MAX_SUPPORTED_VERSION = version(214, Short.MAX_VALUE); + private static final int DEFAULT_VERSION = version(214, 0); private static int version(int major, int minor) { return (major << 16) + minor;