mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-31 04:45:38 +02:00
Bug 460741 - Type of conditional expression in C
Change-Id: I64f4fded197b31e60d81e2fbd5a2728aa8d8d8ce Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
parent
de3c23df86
commit
8607866e33
10 changed files with 271 additions and 34 deletions
|
@ -11052,8 +11052,8 @@ public class AST2CPPTests extends AST2TestBase {
|
|||
ICPPVariable waldo1 = helper.assertNonProblem("waldo1");
|
||||
ICPPVariable waldo2 = helper.assertNonProblem("waldo2");
|
||||
// constexpr on a variable *should* make it const
|
||||
assertSameType(waldo1.getType(), CommonTypes.constInt);
|
||||
assertSameType(waldo2.getType(), CommonTypes.constInt);
|
||||
assertSameType(waldo1.getType(), CommonCPPTypes.constInt);
|
||||
assertSameType(waldo2.getType(), CommonCPPTypes.constInt);
|
||||
}
|
||||
|
||||
// constexpr int waldo1();
|
||||
|
@ -11065,11 +11065,11 @@ public class AST2CPPTests extends AST2TestBase {
|
|||
ICPPFunction waldo2 = helper.assertNonProblem("waldo2");
|
||||
ICPPFunction waldo3 = helper.assertNonProblem("waldo3");
|
||||
// constexpr on a function *should not* make its return type const
|
||||
assertSameType(waldo1.getType().getReturnType(), CommonTypes.int_);
|
||||
assertSameType(waldo1.getType().getReturnType(), CommonCPPTypes.int_);
|
||||
assertSameType(waldo2.getType().getReturnType(),
|
||||
new CPPPointerType(new CPPFunctionType(CommonTypes.int_, new IType[]{ CommonTypes.int_ })));
|
||||
new CPPPointerType(new CPPFunctionType(CommonCPPTypes.int_, new IType[]{ CommonCPPTypes.int_ })));
|
||||
// constexpr on a method *should not* make the method const
|
||||
assertSameType(waldo3.getType(), new CPPFunctionType(CommonTypes.int_, new IType[]{}));
|
||||
assertSameType(waldo3.getType(), new CPPFunctionType(CommonCPPTypes.int_, new IType[]{}));
|
||||
}
|
||||
|
||||
// void waldo() noexcept;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||
|
||||
/**
|
||||
|
@ -314,16 +315,35 @@ public class AST2CSpecTest extends AST2SpecTestBase {
|
|||
}
|
||||
|
||||
// /* Start Example(C 6.5.15-8) */
|
||||
// int f() {
|
||||
// const void *c_vp;
|
||||
// void *vp;
|
||||
// const int *c_ip;
|
||||
// volatile int *v_ip;
|
||||
// int *ip;
|
||||
// const char *c_cp;
|
||||
// }
|
||||
// int f(bool cond) {
|
||||
// const void *c_vp;
|
||||
// void *vp;
|
||||
// const int *c_ip;
|
||||
// volatile int *v_ip;
|
||||
// int *ip;
|
||||
// const char *c_cp;
|
||||
//
|
||||
// cond ? c_vp : c_ip;
|
||||
// cond ? v_ip : 0;
|
||||
// cond ? c_ip : v_ip;
|
||||
// cond ? vp : c_cp;
|
||||
// cond ? ip : c_ip;
|
||||
// cond ? vp : ip;
|
||||
// }
|
||||
public void test6_5_15s8() throws Exception {
|
||||
parseCandCPP(getAboveComment(), true, 0);
|
||||
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), ParserLanguage.C);
|
||||
IASTExpression c1 = helper.assertNode("cond ? c_vp : c_ip");
|
||||
IASTExpression c2 = helper.assertNode("cond ? v_ip : 0");
|
||||
IASTExpression c3 = helper.assertNode("cond ? c_ip : v_ip");
|
||||
IASTExpression c4 = helper.assertNode("cond ? vp : c_cp");
|
||||
IASTExpression c5 = helper.assertNode("cond ? ip : c_ip");
|
||||
IASTExpression c6 = helper.assertNode("cond ? vp : ip");
|
||||
assertSameType(CommonCTypes.pointerToConstVoid, c1.getExpressionType());
|
||||
assertSameType(CommonCTypes.pointerToVolatileInt, c2.getExpressionType());
|
||||
assertSameType(CommonCTypes.pointerToConstVolatileInt, c3.getExpressionType());
|
||||
assertSameType(CommonCTypes.pointerToConstVoid, c4.getExpressionType());
|
||||
assertSameType(CommonCTypes.pointerToConstInt, c5.getExpressionType());
|
||||
assertSameType(CommonCTypes.pointerToVoid, c6.getExpressionType());
|
||||
}
|
||||
|
||||
// /* Start Example(C 6.5.16.1-5) */
|
||||
|
|
|
@ -3280,7 +3280,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
public void testDependentBaseLookup_408314a() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
ITypedef waldo = bh.assertNonProblem("waldo");
|
||||
assertSameType(waldo.getType(), CommonTypes.int_);
|
||||
assertSameType(waldo.getType(), CommonCPPTypes.int_);
|
||||
}
|
||||
|
||||
// template <typename T>
|
||||
|
@ -3302,7 +3302,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
public void testDependentBaseLookup_408314b() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
ITypedef waldo = bh.assertNonProblem("waldo");
|
||||
assertSameType(waldo.getType(), CommonTypes.int_);
|
||||
assertSameType(waldo.getType(), CommonCPPTypes.int_);
|
||||
}
|
||||
|
||||
// template <typename T>
|
||||
|
@ -3324,7 +3324,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
public void testDependentBaseLookup_408314c() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
ITypedef waldo = bh.assertNonProblem("waldo");
|
||||
assertSameType(waldo.getType(), CommonTypes.int_);
|
||||
assertSameType(waldo.getType(), CommonCPPTypes.int_);
|
||||
}
|
||||
|
||||
// template <class T>
|
||||
|
@ -6139,8 +6139,8 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
// auto x2 = begin2(v);
|
||||
public void testResolvingAutoTypeWithDependentExpression_402409a() throws Exception {
|
||||
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
|
||||
helper.assertVariableType("x1", CommonTypes.pointerToInt);
|
||||
helper.assertVariableType("x2", CommonTypes.pointerToInt);
|
||||
helper.assertVariableType("x1", CommonCPPTypes.pointerToInt);
|
||||
helper.assertVariableType("x2", CommonCPPTypes.pointerToInt);
|
||||
}
|
||||
|
||||
// struct vector {
|
||||
|
@ -6314,7 +6314,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
public void testSpecializationOfBaseClass_409078() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
ITypedef waldo = bh.assertNonProblem("waldo");
|
||||
assertSameType(waldo.getType(), CommonTypes.int_);
|
||||
assertSameType(waldo.getType(), CommonCPPTypes.int_);
|
||||
}
|
||||
|
||||
//struct A {
|
||||
|
@ -7836,7 +7836,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
public void testInstantiationOfConstMemberAccess_409107() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
IType waldo = bh.assertNonProblem("waldo");
|
||||
assertSameType(waldo, CommonTypes.int_);
|
||||
assertSameType(waldo, CommonCPPTypes.int_);
|
||||
}
|
||||
|
||||
// template <typename _Tp>
|
||||
|
@ -8253,7 +8253,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
// auto x = foo(N::A());
|
||||
// }
|
||||
public void testUnqualifiedFunctionCallInTemplate_402498b() throws Exception {
|
||||
new BindingAssertionHelper(getAboveComment(), true).assertVariableType("x", CommonTypes.int_);
|
||||
new BindingAssertionHelper(getAboveComment(), true).assertVariableType("x", CommonCPPTypes.int_);
|
||||
}
|
||||
|
||||
// template <typename T>
|
||||
|
@ -8275,7 +8275,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
// analyzer is too lenient and makes it a TypeOfDependentExpression if it
|
||||
// can't instantiate the return type of foo() properly.
|
||||
// That's another bug for another day.
|
||||
assertFalse(x.getType().isSameType(CommonTypes.int_));
|
||||
assertFalse(x.getType().isSameType(CommonCPPTypes.int_));
|
||||
}
|
||||
|
||||
// void bar();
|
||||
|
@ -8326,7 +8326,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
// auto b = foo(a);
|
||||
public void testQualifiedNameLookupInTemplate_402854() throws Exception {
|
||||
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
|
||||
helper.assertVariableType("b", CommonTypes.int_);
|
||||
helper.assertVariableType("b", CommonCPPTypes.int_);
|
||||
}
|
||||
|
||||
// template<typename T> struct A {
|
||||
|
@ -8504,7 +8504,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
public void testDependentDecltypeInNameQualifier_415198() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
helper.assertNonProblem("decltype(foo(T()))::type");
|
||||
assertSameType((ITypedef) helper.assertNonProblem("U<S>::type"), CommonTypes.int_);
|
||||
assertSameType((ITypedef) helper.assertNonProblem("U<S>::type"), CommonCPPTypes.int_);
|
||||
}
|
||||
|
||||
// template <typename T>
|
||||
|
@ -8519,7 +8519,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
// decltype(B::c)::type x;
|
||||
public void testDependentDecltypeInNameQualifier_429837() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
assertSameType((ITypedef) helper.assertNonProblem("decltype(B::c)::type"), CommonTypes.int_);
|
||||
assertSameType((ITypedef) helper.assertNonProblem("decltype(B::c)::type"), CommonCPPTypes.int_);
|
||||
}
|
||||
|
||||
// namespace N {
|
||||
|
|
|
@ -53,7 +53,6 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||
import org.eclipse.cdt.core.dom.ast.IField;
|
||||
|
@ -90,6 +89,9 @@ import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
|||
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.CBasicType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.CPointerType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.CQualifierType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.GNUCSourceParser;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||
|
@ -109,8 +111,29 @@ public class AST2TestBase extends BaseTestCase {
|
|||
protected static final IParserLogService NULL_LOG = new NullLogService();
|
||||
protected static boolean sValidateCopy;
|
||||
|
||||
protected static class CommonTypes {
|
||||
public static IType int_ = new CPPBasicType(Kind.eInt, 0);
|
||||
protected static class CommonCTypes {
|
||||
public static IType pointerToVoid = pointerTo(CBasicType.VOID);
|
||||
public static IType pointerToConstVoid = pointerTo(constOf(CBasicType.VOID));
|
||||
public static IType pointerToConstInt = pointerTo(constOf(CBasicType.INT));
|
||||
public static IType pointerToVolatileInt = pointerTo(volatileOf(CBasicType.INT));
|
||||
public static IType pointerToConstVolatileInt = pointerTo(constVolatileOf(CBasicType.INT));
|
||||
|
||||
private static IType pointerTo(IType type) {
|
||||
return new CPointerType(type, 0);
|
||||
}
|
||||
private static IType constOf(IType type) {
|
||||
return new CQualifierType(type, true, false, false);
|
||||
}
|
||||
private static IType volatileOf(IType type) {
|
||||
return new CQualifierType(type, false, true, false);
|
||||
}
|
||||
private static IType constVolatileOf(IType type) {
|
||||
return new CQualifierType(type, true, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class CommonCPPTypes {
|
||||
public static IType int_ = CPPBasicType.INT;
|
||||
public static IType pointerToInt = new CPPPointerType(int_);
|
||||
public static IType constInt = new CPPQualifierType(int_, true, false);
|
||||
}
|
||||
|
|
|
@ -7582,4 +7582,17 @@ public class AST2Tests extends AST2TestBase {
|
|||
IFunction waldo = bh.assertNonProblem("waldo");
|
||||
assertTrue(waldo.getType().takesVarArgs());
|
||||
}
|
||||
|
||||
// struct Foo {
|
||||
// struct Foo* a;
|
||||
// };
|
||||
//
|
||||
// int main() {
|
||||
// struct Foo * f = 0;
|
||||
// (f ? f->a : ((void*) 0))->a; // second 'a' cannot be resolved
|
||||
// return 0;
|
||||
// }
|
||||
public void testVoidPointerInTernaryOperator_460741() throws Exception {
|
||||
parseAndCheckBindings(getAboveComment(), C);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,13 +13,18 @@
|
|||
package org.eclipse.cdt.internal.core.dom.parser.c;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes;
|
||||
|
||||
/**
|
||||
* Conditional expression in C
|
||||
|
@ -151,13 +156,76 @@ public class CASTConditionalExpression extends ASTNode implements
|
|||
if (positiveExpression == null) {
|
||||
positiveExpression= getLogicalConditionExpression();
|
||||
}
|
||||
IType t2 = positiveExpression.getExpressionType();
|
||||
IType t3 = getNegativeResultExpression().getExpressionType();
|
||||
if (t3 instanceof IPointerType || t2 == null)
|
||||
return t3;
|
||||
return t2;
|
||||
IASTExpression negativeExpression = getNegativeResultExpression();
|
||||
IType originalPositiveType = positiveExpression.getExpressionType();
|
||||
IType originalNegativeType = getNegativeResultExpression().getExpressionType();
|
||||
IType positiveType = CVisitor.unwrapTypedefs(originalPositiveType);
|
||||
IType negativeType = CVisitor.unwrapTypedefs(originalNegativeType);
|
||||
IType resultType = computeResultType(positiveExpression, negativeExpression,
|
||||
positiveType, negativeType);
|
||||
if (resultType == null) {
|
||||
return ProblemType.UNKNOWN_FOR_EXPRESSION;
|
||||
}
|
||||
return ExpressionTypes.restoreTypedefs(resultType, originalPositiveType, originalPositiveType);
|
||||
}
|
||||
|
||||
|
||||
private IType computeResultType(IASTExpression positiveExpression, IASTExpression negativeExpression,
|
||||
IType positiveType, IType negativeType) {
|
||||
// [6.5.15] p5: If both the second and third operands have arithmetic type, the result type
|
||||
// that would be determined by the usual arithmetic conversions, were they applied to those
|
||||
// two operands, is the type of the result. If both operands have void type, the result has
|
||||
// void type.
|
||||
if (positiveType instanceof IBasicType && negativeType instanceof IBasicType) {
|
||||
if (((IBasicType) positiveType).getKind() == IBasicType.Kind.eVoid
|
||||
&& ((IBasicType) negativeType).getKind() == IBasicType.Kind.eVoid) {
|
||||
return CBasicType.VOID;
|
||||
}
|
||||
|
||||
// It doesn't really matter which operator we use here, so we'll use op_plus.
|
||||
return CArithmeticConversion.convertCOperandTypes(IASTBinaryExpression.op_plus,
|
||||
positiveType, negativeType);
|
||||
}
|
||||
|
||||
// If both the operands have structure or union type, the result has that type.
|
||||
if (positiveType instanceof ICompositeType && negativeType instanceof ICompositeType) {
|
||||
// Both operands must have the same structure or union type as per p3.
|
||||
if (positiveType.isSameType(negativeType)) {
|
||||
return positiveType;
|
||||
}
|
||||
}
|
||||
|
||||
// [6.5.15] p6: If both the second and third operands are pointers or one is a null pointer
|
||||
// constant and the other is a pointer, the result type is a pointer to a type qualified with
|
||||
// all the type qualifiers of the types referenced by both operands. Furthermore, if both
|
||||
// operands are pointers to compatible types or to differently qualified versions of compatible
|
||||
// types, the result type is a pointer to an appropriately qualified version of the composite
|
||||
// type; if one operand is a null pointer constant, the result has the type of the other operand;
|
||||
// otherwise, one operand is a pointer to void or a qualified version of void, in which case the
|
||||
// result type is a pointer to an appropriately qualified version of void.
|
||||
if (CVisitor.isNullPointerConstant(positiveExpression) && negativeType instanceof IPointerType) {
|
||||
return negativeType;
|
||||
} else if (CVisitor.isNullPointerConstant(negativeExpression) && positiveType instanceof IPointerType) {
|
||||
return positiveType;
|
||||
} else if (positiveType instanceof IPointerType && negativeType instanceof IPointerType) {
|
||||
IType positivePointeeCV = ((IPointerType) positiveType).getType();
|
||||
IType negativePointeeCV = ((IPointerType) negativeType).getType();
|
||||
IType positivePointee = CVisitor.unwrapCV(positivePointeeCV);
|
||||
IType negativePointee = CVisitor.unwrapCV(negativePointeeCV);
|
||||
IType resultPointee;
|
||||
if (positivePointee.isSameType(CBasicType.VOID) || negativePointee.isSameType(CBasicType.VOID)) {
|
||||
resultPointee = CBasicType.VOID;
|
||||
} else {
|
||||
// TODO: Implement checking for compatible types and computing the composite type.
|
||||
resultPointee = negativePointee;
|
||||
}
|
||||
return new CPointerType(
|
||||
ExpressionTypes.restoreCV(resultPointee, positivePointeeCV, negativePointeeCV), 0);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLValue() {
|
||||
return false;
|
||||
|
|
|
@ -23,6 +23,9 @@ import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
|||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class CBasicType implements ICBasicType, ISerializableType {
|
||||
public static final CBasicType VOID = new CBasicType(Kind.eVoid, 0, null);
|
||||
public static final CBasicType INT = new CBasicType(Kind.eInt, 0, null);
|
||||
|
||||
private final Kind fKind;
|
||||
private int fModifiers;
|
||||
private IASTExpression value;
|
||||
|
|
|
@ -20,6 +20,8 @@ import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
|||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class CPointerType implements ICPointerType, ITypeContainer, ISerializableType {
|
||||
static public final CPointerType VOID_POINTER = new CPointerType(CBasicType.VOID, 0);
|
||||
|
||||
static public final int IS_CONST = 1;
|
||||
static public final int IS_RESTRICT = 1 << 1;
|
||||
static public final int IS_VOLATILE = 1 << 2;
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTAttribute;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||
|
@ -58,6 +59,7 @@ import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
|
@ -70,12 +72,15 @@ import org.eclipse.cdt.core.dom.ast.IFunction;
|
|||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.ILabel;
|
||||
import org.eclipse.cdt.core.dom.ast.IParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope.ScopeLookupData;
|
||||
import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTArrayModifier;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier;
|
||||
|
@ -105,6 +110,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
||||
import org.eclipse.cdt.internal.core.parser.util.ContentAssistMatcherFactory;
|
||||
|
||||
|
@ -714,6 +720,16 @@ public class CVisitor extends ASTQueries {
|
|||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static IType unwrapCV(IType type) {
|
||||
while (type instanceof IQualifierType) {
|
||||
type = ((IQualifierType) type).getType();
|
||||
}
|
||||
if (type instanceof IPointerType) {
|
||||
type = new CPointerType(((IPointerType) type).getType(), 0 /* no qualifiers */);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parent
|
||||
|
@ -1278,6 +1294,9 @@ public class CVisitor extends ASTQueries {
|
|||
|
||||
return type;
|
||||
}
|
||||
private static IType createType(IASTTypeId typeId) {
|
||||
return createType(typeId.getAbstractDeclarator());
|
||||
}
|
||||
|
||||
public static IType createType(IType baseType, IASTDeclarator declarator) {
|
||||
if (declarator instanceof IASTFunctionDeclarator)
|
||||
|
@ -1742,4 +1761,39 @@ public class CVisitor extends ASTQueries {
|
|||
|
||||
return name.resolveBinding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an expression is a null pointer constant.
|
||||
*/
|
||||
public static boolean isNullPointerConstant(IASTExpression expression) {
|
||||
// [6.3.2.3] p3: An integer constant expression with the value 0, or such an expression cast
|
||||
// to void*, is called a null pointer constant.
|
||||
|
||||
// Unwrap extra parentheses.
|
||||
if (expression instanceof IASTUnaryExpression) {
|
||||
IASTUnaryExpression unaryExpression = (IASTUnaryExpression) expression;
|
||||
if (unaryExpression.getOperator() == IASTUnaryExpression.op_bracketedPrimary) {
|
||||
return isNullPointerConstant(unaryExpression.getOperand());
|
||||
}
|
||||
}
|
||||
|
||||
if (expression instanceof IASTCastExpression) {
|
||||
IASTCastExpression castExpression = (IASTCastExpression) expression;
|
||||
IType castType = createType(castExpression.getTypeId());
|
||||
if (castType.isSameType(CPointerType.VOID_POINTER)) {
|
||||
return isNullPointerConstant(castExpression.getOperand());
|
||||
}
|
||||
}
|
||||
|
||||
IType expressionType = expression.getExpressionType();
|
||||
if (expressionType instanceof IBasicType) {
|
||||
IValue value = Value.create(expression);
|
||||
if (value != null && value.numericalValue() != null) {
|
||||
return value.numericalValue().longValue() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,14 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICQualifierType;
|
||||
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.ICPPReferenceType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.CQualifierType;
|
||||
|
||||
/**
|
||||
* Methods for computing the type of an expression.
|
||||
|
@ -89,4 +93,54 @@ public class ExpressionTypes {
|
|||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static boolean isConst(IType type) {
|
||||
if (type instanceof IQualifierType) {
|
||||
return ((IQualifierType) type).isConst();
|
||||
} else if (type instanceof IPointerType) {
|
||||
return ((IPointerType) type).isConst();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isVolatile(IType type) {
|
||||
if (type instanceof IQualifierType) {
|
||||
return ((IQualifierType) type).isVolatile();
|
||||
} else if (type instanceof IPointerType) {
|
||||
return ((IPointerType) type).isVolatile();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static IType makeConst(IType type) {
|
||||
if (type instanceof ICQualifierType) {
|
||||
ICQualifierType qualifierType = ((ICQualifierType) type);
|
||||
return new CQualifierType(qualifierType.getType(),
|
||||
true, qualifierType.isVolatile(), qualifierType.isRestrict());
|
||||
}
|
||||
return new CQualifierType(type, true, false, false);
|
||||
}
|
||||
|
||||
private static IType makeVolatile(IType type) {
|
||||
if (type instanceof ICQualifierType) {
|
||||
ICQualifierType qualifierType = ((ICQualifierType) type);
|
||||
return new CQualifierType(qualifierType.getType(),
|
||||
qualifierType.isConst(), true, qualifierType.isRestrict());
|
||||
}
|
||||
return new CQualifierType(type, false, true, false);
|
||||
}
|
||||
|
||||
private static IType restoreCV(IType type, IType originalType) {
|
||||
if (isConst(originalType)) {
|
||||
type = makeConst(type);
|
||||
}
|
||||
if (isVolatile(originalType)) {
|
||||
type = makeVolatile(type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public static IType restoreCV(IType type, IType originalType1, IType originalType2) {
|
||||
return restoreCV(restoreCV(type, originalType1), originalType2);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue