mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 14:12:10 +02:00
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 <hannes@havogt.de>
This commit is contained in:
parent
0552fcbf97
commit
f938b4d08e
44 changed files with 531 additions and 46 deletions
|
@ -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<int>(t));
|
||||
// constexpr bool not_noexcept_conversion = noexcept(static_cast<int*>(t));
|
||||
// constexpr bool conversion_from_constructor = noexcept(static_cast<int*>(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<typename T>
|
||||
// int funt(T);
|
||||
// template<typename T>
|
||||
// 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<int (*)(int)>(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 <bool B>
|
||||
// void foo() noexcept(B);
|
||||
//
|
||||
// constexpr bool is_noexcept = noexcept(foo<true>());
|
||||
// constexpr bool is_not_noexcept = noexcept(foo<false>());
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<>();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() + " <op> " + 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,4 +167,9 @@ public class EvalBinaryTypeId extends CPPDependentEvaluation {
|
|||
public boolean referencesTemplateParameter() {
|
||||
return isValueDependent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNoexcept() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -532,4 +532,9 @@ public class EvalBinding extends CPPDependentEvaluation {
|
|||
public String toString() {
|
||||
return getBinding().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNoexcept() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,4 +142,9 @@ public class EvalCompoundStatementExpression extends CPPDependentEvaluation {
|
|||
public boolean referencesTemplateParameter() {
|
||||
return fDelegate.referencesTemplateParameter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNoexcept() {
|
||||
return fDelegate.isNoexcept();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -470,4 +470,9 @@ public class EvalMemberAccess extends CPPDependentEvaluation {
|
|||
public boolean referencesTemplateParameter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNoexcept() {
|
||||
return fOwnerEval.isNoexcept();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -193,4 +193,10 @@ public class EvalReference extends CPPDependentEvaluation {
|
|||
return new EvalReference(record, referredBinding, templateDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNoexcept() {
|
||||
assert false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -297,4 +297,9 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation {
|
|||
}
|
||||
return EvalFixed.INCOMPLETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNoexcept() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue