From deabf0e68b844db6965abc77dcc7571c04e8a16a Mon Sep 17 00:00:00 2001 From: John Camelon Date: Thu, 18 Nov 2004 14:34:42 +0000 Subject: [PATCH] Patch for Devin Steffler. Fixed 77821 - usualArithmeticConversions doesn't handle pointers --- .../parser/tests/CompleteParseASTTest.java | 9 +++ .../ast/complete/CompleteParseASTFactory.java | 64 +++++++++++++++++-- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java index bab133316f8..e6d0d82376d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java @@ -2332,5 +2332,14 @@ public class CompleteParseASTTest extends CompleteParseBaseTest writer.write("#endif\n"); //$NON-NLS-1$ parse(writer.toString()); } + + public void testBug77821() throws Exception { + Writer writer = new StringWriter(); + writer.write("typedef struct { /* ... */ }TYPE;\n"); //$NON-NLS-1$ + writer.write("void ptrArith(const TYPE* pType) {\n"); //$NON-NLS-1$ + writer.write("TYPE *temp = 0;\n"); //$NON-NLS-1$ + writer.write("temp = (TYPE*)(pType + 1); /* Parser error is here */\n}\n"); //$NON-NLS-1$ + parse(writer.toString()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java index 5927f7ba0b6..6c2244464eb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java @@ -1368,7 +1368,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto * Apply the usual arithmetic conversions to find out the result of an expression * that has a lhs and a rhs as indicated in the specs (section 5.Expressions, page 64) */ - protected ITypeInfo usualArithmeticConversions( IASTScope scope, ASTExpression lhsExp, ASTExpression rhsExp) throws ASTSemanticException{ + protected ITypeInfo usualArithmeticConversions( IASTScope scope, ASTExpression lhsExp, ASTExpression rhsExp, Kind kind) throws ASTSemanticException{ setFilename(lhsExp.getFilename()); ITypeInfo lhs = lhsExp.getResultType().getResult(); @@ -1376,18 +1376,62 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto if( lhs == null ) return null; if( rhs == null ) return null; + boolean isLhsPointer = false; + boolean isRhsPointer = false; // if you have a variable of type basic type, then we need to go to the basic type first while( (lhs.getType() == ITypeInfo.t_type) && (lhs.getTypeSymbol() != null)){ + if (!isLhsPointer) isLhsPointer = lhs.hasPtrOperators(); lhs = lhs.getTypeSymbol().getTypeInfo(); } while( (rhs.getType() == ITypeInfo.t_type) && (rhs.getTypeSymbol() != null)){ + if (!isRhsPointer) isRhsPointer = rhs.hasPtrOperators(); rhs = rhs.getTypeSymbol().getTypeInfo(); } - if( !lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) ) - handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); - if( !rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) ) - handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); + // invalid arithmetic detection TODO add support for 4.5 Integral Promotions/4.7 Integral Conversions if necessary + // 5.6 Multiplicative Operators: The operands of * and / shall have arithmetic or enumeration type; the operands of % shall have integral or enumeration type. + if (kind == IASTExpression.Kind.MULTIPLICATIVE_MULTIPLY || kind == IASTExpression.Kind.MULTIPLICATIVE_DIVIDE) { + if( !lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) ) + handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); // TODO Devin used to be true + if( !rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) ) + handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); // TODO Devin used to be true + } else if (kind == IASTExpression.Kind.MULTIPLICATIVE_MODULUS) { + if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) )) + handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); // TODO Devin used to be true + if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) )) + handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); // TODO Devin used to be true + + // 5.7 Additive Operators: + // For addition, either both operands shall have arithmetic or enumeration type, or one operand shall be a + // pointer to a completely defined object type and the other shall have integral or enumeration type. + // For subtraction, one of the following shall hold: + // — both operands have arithmetic or enumeration type; or + // — both operands are pointers to cvqualified or cvunqualified versions of the same completely defined object type; or + // — the left operand is a pointer to a completely defined object type and the right operand has integral or + // enumeration type. + } else if (kind == IASTExpression.Kind.ADDITIVE_PLUS) { + if (!((isLhsPointer && (isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ))) || + (isRhsPointer && (isIntegralType(lhs, isRhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ))))) { + if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) ) + handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); // TODO Devin used to be true + if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) ) + handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); // TODO Devin used to be true + } + } else if (kind == IASTExpression.Kind.ADDITIVE_MINUS) { + if (!(isLhsPointer && (isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )))) { + if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) ) + handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); // TODO Devin used to be true + if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) ) + handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); // TODO Devin used to be true + } + + // 5.11, 5.12, 5.13: The operator applies only to integral or enumeration operands. + } else if (kind == IASTExpression.Kind.ANDEXPRESSION || kind == IASTExpression.Kind.EXCLUSIVEOREXPRESSION || kind == IASTExpression.Kind.INCLUSIVEOREXPRESSION) { + if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) ) + handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); // TODO Devin used to be true + if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) ) + handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); // TODO Devin used to be true + } ITypeInfo info = TypeInfoProvider.newTypeInfo( ); if( @@ -1739,7 +1783,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto ASTExpression left = (ASTExpression)lhs; ASTExpression right = (ASTExpression)rhs; if((left != null ) && (right != null)){ - info = usualArithmeticConversions( scope, left, right); + info = usualArithmeticConversions( scope, left, right, kind ); } else handleProblem( scope, IProblem.SEMANTIC_MALFORMED_EXPRESSION, null ); @@ -3812,4 +3856,12 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto this.filename = EMPTY_STRING; } } + + // used to check if an ITypeInfo is an "integral type" based on 3.9.1-7 + private boolean isIntegralType(ITypeInfo info, boolean isPointer) { + if (isPointer) return true; + if (info.getType() == ITypeInfo.t_bool || info.getType() == ITypeInfo.t_char || info.getType() == ITypeInfo.t_wchar_t || info.getType() == ITypeInfo.t_int) return true; + + return false; + } }