1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Computing the correct type for pointer arithmetics.

This commit is contained in:
Markus Schorn 2008-04-28 13:05:49 +00:00
parent d772cf26d6
commit 846e2a2320
3 changed files with 145 additions and 100 deletions

View file

@ -4673,4 +4673,29 @@ public class AST2Tests extends AST2BaseTest {
} }
} }
} }
// struct S {
// int value;
// };
// typedef struct S *PtrS;
// struct T {
// PtrS ptrS;
// };
//
// void testint(int x);
// void testptr(struct T* x);
//
// void test() {
// struct T* t;
// t->ptrS->value;
// (t->ptrS+1)->value;
// testptr(t-0);
// testint(t-t);
// testint(0-t);
// }
public void testTypeOfPointerOperations() throws Exception {
String code= getAboveComment();
parseAndCheckBindings(code, ParserLanguage.C);
parseAndCheckBindings(code, ParserLanguage.CPP);
}
} }

View file

@ -466,6 +466,7 @@ public class CVisitor {
protected static final ASTNodeProperty STRING_LOOKUP_PROPERTY = new ASTNodeProperty("CVisitor.STRING_LOOKUP_PROPERTY - STRING_LOOKUP"); //$NON-NLS-1$ protected static final ASTNodeProperty STRING_LOOKUP_PROPERTY = new ASTNodeProperty("CVisitor.STRING_LOOKUP_PROPERTY - STRING_LOOKUP"); //$NON-NLS-1$
protected static final ASTNodeProperty STRING_LOOKUP_TAGS_PROPERTY = new ASTNodeProperty("CVisitor.STRING_LOOKUP_TAGS_PROPERTY - STRING_LOOKUP"); //$NON-NLS-1$ protected static final ASTNodeProperty STRING_LOOKUP_TAGS_PROPERTY = new ASTNodeProperty("CVisitor.STRING_LOOKUP_TAGS_PROPERTY - STRING_LOOKUP"); //$NON-NLS-1$
private static final String SIZE_T = "size_t"; //$NON-NLS-1$ private static final String SIZE_T = "size_t"; //$NON-NLS-1$
private static final String PTRDIFF_T = "ptrdiff_t"; //$NON-NLS-1$
public static final String EMPTY_STRING = ""; //$NON-NLS-1$ public static final String EMPTY_STRING = ""; //$NON-NLS-1$
public static final char [] EMPTY_CHAR_ARRAY = "".toCharArray(); //$NON-NLS-1$ public static final char [] EMPTY_CHAR_ARRAY = "".toCharArray(); //$NON-NLS-1$
//lookup bits //lookup bits
@ -708,7 +709,6 @@ public class CVisitor {
} else if( expression instanceof IASTBinaryExpression ){ } else if( expression instanceof IASTBinaryExpression ){
IASTBinaryExpression binary = (IASTBinaryExpression) expression; IASTBinaryExpression binary = (IASTBinaryExpression) expression;
int op = binary.getOperator(); int op = binary.getOperator();
IType result = null;
switch( op ){ switch( op ){
case IASTBinaryExpression.op_lessEqual: case IASTBinaryExpression.op_lessEqual:
case IASTBinaryExpression.op_lessThan: case IASTBinaryExpression.op_lessThan:
@ -718,25 +718,39 @@ public class CVisitor {
case IASTBinaryExpression.op_logicalOr: case IASTBinaryExpression.op_logicalOr:
case IASTBinaryExpression.op_equals: case IASTBinaryExpression.op_equals:
case IASTBinaryExpression.op_notequals: case IASTBinaryExpression.op_notequals:
result = new CBasicType( IBasicType.t_int, 0 ); CBasicType basicType = new CBasicType( IBasicType.t_int, 0 );
break; basicType.setValue(expression);
return basicType;
case IASTBinaryExpression.op_plus: case IASTBinaryExpression.op_plus:
case IASTBinaryExpression.op_minus: IType t2 = getExpressionType(binary.getOperand2());
IType t = getExpressionType( ((IASTBinaryExpression) expression).getOperand1() ); if (unwrapTypedefs(t2) instanceof IPointerType) {
if( t instanceof IPointerType ) return t2;
result = t; }
else{ break;
result = getExpressionType( ((IASTBinaryExpression) expression).getOperand2() );
case IASTBinaryExpression.op_minus:
t2= getExpressionType(binary.getOperand2());
if (unwrapTypedefs(t2) instanceof IPointerType) {
IType t1 = getExpressionType(binary.getOperand1());
if (unwrapTypedefs(t1) instanceof IPointerType) {
IScope scope = getContainingScope(expression);
try {
IBinding[] bs = scope.find(PTRDIFF_T);
if (bs.length > 0 && bs[0] instanceof IType) {
return (IType) bs[0];
}
} catch (DOMException e) {
}
basicType = new CBasicType(IBasicType.t_int, CBasicType.IS_UNSIGNED | CBasicType.IS_LONG);
basicType.setValue(expression);
return basicType;
}
return t1;
} }
break; break;
default:
result = getExpressionType( ((IASTBinaryExpression) expression).getOperand1() );
} }
return getExpressionType(binary.getOperand1() );
if( result instanceof CBasicType ){
((CBasicType)result).setValue( expression );
}
return result;
} else if( expression instanceof IASTUnaryExpression ) { } else if( expression instanceof IASTUnaryExpression ) {
int op = ((IASTUnaryExpression)expression).getOperator(); int op = ((IASTUnaryExpression)expression).getOperator();
if( op == IASTUnaryExpression.op_sizeof ){ if( op == IASTUnaryExpression.op_sizeof ){
@ -816,6 +830,14 @@ public class CVisitor {
} }
return null; return null;
} }
private static IType unwrapTypedefs(IType type) throws DOMException {
while (type instanceof ITypedef) {
type= ((ITypedef) type).getType();
}
return type;
}
/** /**
* @param parent * @param parent
* @return * @return

View file

@ -185,6 +185,7 @@ import org.eclipse.cdt.internal.core.index.IIndexScope;
*/ */
public class CPPVisitor { public class CPPVisitor {
public static final String SIZE_T = "size_t"; //$NON-NLS-1$ public static final String SIZE_T = "size_t"; //$NON-NLS-1$
public static final String PTRDIFF_T = "ptrdiff_t"; //$NON-NLS-1$
/** /**
* @param name * @param name
@ -638,8 +639,8 @@ public class CPPVisitor {
ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name); ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name);
if (templateDecl != null) { if (templateDecl != null) {
ICPPASTTemplateParameter[] params = templateDecl.getTemplateParameters(); ICPPASTTemplateParameter[] params = templateDecl.getTemplateParameters();
for (int i = 0; i < params.length; i++) { for (ICPPASTTemplateParameter param : params) {
IASTName paramName = CPPTemplates.getTemplateParameterName(params[i]); IASTName paramName = CPPTemplates.getTemplateParameterName(param);
paramName.setBinding(null); paramName.setBinding(null);
//unsetting the index bindings so that they //unsetting the index bindings so that they
//can be re-resolved with normal bindings //can be re-resolved with normal bindings
@ -675,7 +676,7 @@ public class CPPVisitor {
} else { } else {
binding = new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, declarator.getName().toCharArray()); binding = new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, declarator.getName().toCharArray());
} }
} else if (simpleDecl.getParent() instanceof ICPPASTCompositeTypeSpecifier) { } else if (simpleDecl != null && simpleDecl.getParent() instanceof ICPPASTCompositeTypeSpecifier) {
binding = new CPPField(name); binding = new CPPField(name);
} else { } else {
binding = new CPPVariable(name); binding = new CPPVariable(name);
@ -1193,6 +1194,7 @@ public class CPPVisitor {
} }
} }
@SuppressWarnings("fallthrough")
@Override @Override
public int visit(IASTName name) { public int visit(IASTName name) {
if (name instanceof ICPPASTQualifiedName) return PROCESS_CONTINUE; if (name instanceof ICPPASTQualifiedName) return PROCESS_CONTINUE;
@ -1248,7 +1250,8 @@ public class CPPVisitor {
if (kind == KIND_TYPE) if (kind == KIND_TYPE)
return PROCESS_CONTINUE; return PROCESS_CONTINUE;
// fall through
case KIND_OBJ_FN: case KIND_OBJ_FN:
if (prop == IASTDeclarator.DECLARATOR_NAME || if (prop == IASTDeclarator.DECLARATOR_NAME ||
prop == IASTEnumerationSpecifier.IASTEnumerator.ENUMERATOR_NAME || prop == IASTEnumerationSpecifier.IASTEnumerator.ENUMERATOR_NAME ||
@ -1281,13 +1284,13 @@ public class CPPVisitor {
private boolean isDeclarationsBinding(IBinding nameBinding) { private boolean isDeclarationsBinding(IBinding nameBinding) {
nameBinding= unwindBinding(nameBinding); nameBinding= unwindBinding(nameBinding);
if (nameBinding != null) { if (nameBinding != null) {
for (int i = 0; i < bindings.length; i++) { for (IBinding binding : bindings) {
if (nameBinding.equals(unwindBinding(bindings[i]))) { if (nameBinding.equals(unwindBinding(binding))) {
return true; return true;
} }
// a using declaration is a declaration for the references of its delegates // a using declaration is a declaration for the references of its delegates
if (nameBinding instanceof ICPPUsingDeclaration) { if (nameBinding instanceof ICPPUsingDeclaration) {
if (ArrayUtil.contains(((ICPPUsingDeclaration) nameBinding).getDelegates(), bindings[i])) { if (ArrayUtil.contains(((ICPPUsingDeclaration) nameBinding).getDelegates(), binding)) {
return true; return true;
} }
} }
@ -1357,6 +1360,7 @@ public class CPPVisitor {
} }
} }
@SuppressWarnings("fallthrough")
@Override @Override
public int visit(IASTName name) { public int visit(IASTName name) {
if (name instanceof ICPPASTQualifiedName || name instanceof ICPPASTTemplateId) if (name instanceof ICPPASTQualifiedName || name instanceof ICPPASTTemplateId)
@ -1394,6 +1398,8 @@ public class CPPVisitor {
} }
if (kind == KIND_TYPE) if (kind == KIND_TYPE)
return PROCESS_CONTINUE; return PROCESS_CONTINUE;
// fall through
case KIND_OBJ_FN: case KIND_OBJ_FN:
if (prop == IASTIdExpression.ID_NAME || if (prop == IASTIdExpression.ID_NAME ||
prop == IASTFieldReference.FIELD_NAME || prop == IASTFieldReference.FIELD_NAME ||
@ -1433,15 +1439,14 @@ public class CPPVisitor {
private boolean isReferenceBinding(IBinding nameBinding) { private boolean isReferenceBinding(IBinding nameBinding) {
nameBinding= unwindBinding(nameBinding); nameBinding= unwindBinding(nameBinding);
if (nameBinding != null) { if (nameBinding != null) {
for (int i = 0; i < bindings.length; i++) { for (IBinding binding : bindings) {
if (nameBinding.equals(bindings[i])) { if (nameBinding.equals(binding)) {
return true; return true;
} }
} }
if (nameBinding instanceof ICPPUsingDeclaration) { if (nameBinding instanceof ICPPUsingDeclaration) {
IBinding[] delegates= ((ICPPUsingDeclaration) nameBinding).getDelegates(); IBinding[] delegates= ((ICPPUsingDeclaration) nameBinding).getDelegates();
for (int i = 0; i < delegates.length; i++) { for (IBinding delegate : delegates) {
IBinding delegate = delegates[i];
if (isReferenceBinding(delegate)) { if (isReferenceBinding(delegate)) {
return true; return true;
} }
@ -1469,7 +1474,6 @@ public class CPPVisitor {
* NOTE: This does not currectly handle parameters with typedef types. * NOTE: This does not currectly handle parameters with typedef types.
* @param returnType * @param returnType
* @param parameters * @param parameters
* @return
*/ */
public static IFunctionType createImplicitFunctionType(IType returnType, IParameter[] parameters) { public static IFunctionType createImplicitFunctionType(IType returnType, IParameter[] parameters) {
@ -1579,24 +1583,24 @@ public class CPPVisitor {
private static IType getPointerTypes(IType type, IASTDeclarator declarator) { private static IType getPointerTypes(IType type, IASTDeclarator declarator) {
IASTPointerOperator[] ptrOps = declarator.getPointerOperators(); IASTPointerOperator[] ptrOps = declarator.getPointerOperators();
for (int i = 0; i < ptrOps.length; i++) { for (IASTPointerOperator ptrOp : ptrOps) {
if (ptrOps[i] instanceof IGPPASTPointerToMember) if (ptrOp instanceof IGPPASTPointerToMember)
type = new GPPPointerToMemberType(type, (IGPPASTPointerToMember) ptrOps[i]); type = new GPPPointerToMemberType(type, (IGPPASTPointerToMember) ptrOp);
else if (ptrOps[i] instanceof ICPPASTPointerToMember) else if (ptrOp instanceof ICPPASTPointerToMember)
type = new CPPPointerToMemberType(type, (ICPPASTPointerToMember) ptrOps[i]); type = new CPPPointerToMemberType(type, (ICPPASTPointerToMember) ptrOp);
else if (ptrOps[i] instanceof IGPPASTPointer) else if (ptrOp instanceof IGPPASTPointer)
type = new GPPPointerType(type, (IGPPASTPointer) ptrOps[i]); type = new GPPPointerType(type, (IGPPASTPointer) ptrOp);
else if (ptrOps[i] instanceof IASTPointer) else if (ptrOp instanceof IASTPointer)
type = new CPPPointerType(type, (IASTPointer) ptrOps[i]); type = new CPPPointerType(type, (IASTPointer) ptrOp);
else if (ptrOps[i] instanceof ICPPASTReferenceOperator) else if (ptrOp instanceof ICPPASTReferenceOperator)
type = new CPPReferenceType(type); type = new CPPReferenceType(type);
} }
return type; return type;
} }
private static IType getArrayTypes(IType type, IASTArrayDeclarator declarator) { private static IType getArrayTypes(IType type, IASTArrayDeclarator declarator) {
IASTArrayModifier[] mods = declarator.getArrayModifiers(); IASTArrayModifier[] mods = declarator.getArrayModifiers();
for (int i = 0; i < mods.length; i++) { for (IASTArrayModifier mod : mods) {
type = new CPPArrayType(type, mods[i].getConstantExpression()); type = new CPPArrayType(type, mod.getConstantExpression());
} }
return type; return type;
} }
@ -1612,10 +1616,7 @@ public class CPPVisitor {
return createType(((IASTParameterDeclaration)node).getDeclarator()); return createType(((IASTParameterDeclaration)node).getDeclarator());
return null; return null;
} }
/**
* @param declarator
* @return
*/
public static IType createType(IASTDeclarator declarator) { public static IType createType(IASTDeclarator declarator) {
IASTDeclSpecifier declSpec = null; IASTDeclSpecifier declSpec = null;
@ -1638,10 +1639,7 @@ public class CPPVisitor {
type = createType(type, declarator); type = createType(type, declarator);
return type; return type;
} }
/**
* @param declSpec
* @return
*/
public static IType createType(IASTDeclSpecifier declSpec) { public static IType createType(IASTDeclSpecifier declSpec) {
IType type = getBaseType(declSpec); IType type = getBaseType(declSpec);
@ -1751,10 +1749,6 @@ public class CPPVisitor {
return null; return null;
} }
/**
* @param expression
* @return
*/
public static IType getExpressionType(IASTExpression expression) { public static IType getExpressionType(IASTExpression expression) {
if (expression == null) if (expression == null)
return null; return null;
@ -1856,50 +1850,59 @@ public class CPPVisitor {
return (IType) binding; return (IType) binding;
} }
} else if (expression instanceof IASTBinaryExpression) { } else if (expression instanceof IASTBinaryExpression) {
IASTBinaryExpression binary = (IASTBinaryExpression) expression; final IASTBinaryExpression binary = (IASTBinaryExpression) expression;
int op = binary.getOperator(); final int op = binary.getOperator();
IType result = null; switch(op) {
switch(op) { case IASTBinaryExpression.op_lessEqual:
case IASTBinaryExpression.op_lessEqual: case IASTBinaryExpression.op_lessThan:
case IASTBinaryExpression.op_lessThan: case IASTBinaryExpression.op_greaterEqual:
case IASTBinaryExpression.op_greaterEqual: case IASTBinaryExpression.op_greaterThan:
case IASTBinaryExpression.op_greaterThan: case IASTBinaryExpression.op_logicalAnd:
case IASTBinaryExpression.op_logicalAnd: case IASTBinaryExpression.op_logicalOr:
case IASTBinaryExpression.op_logicalOr: case IASTBinaryExpression.op_equals:
case IASTBinaryExpression.op_equals: case IASTBinaryExpression.op_notequals:
case IASTBinaryExpression.op_notequals: CPPBasicType basicType= new CPPBasicType(ICPPBasicType.t_bool, 0);
result = new CPPBasicType(ICPPBasicType.t_bool, 0); basicType.setValue(expression);
break; return basicType;
case IASTBinaryExpression.op_plus: case IASTBinaryExpression.op_plus:
case IASTBinaryExpression.op_minus: IType t2 = getExpressionType(binary.getOperand2());
IType t = getExpressionType(((IASTBinaryExpression) expression).getOperand1()); if (SemanticUtil.getUltimateTypeViaTypedefs(t2) instanceof IPointerType) {
if (t instanceof IPointerType) return t2;
result = t; }
else{ break;
result = getExpressionType(((IASTBinaryExpression) expression).getOperand2()); case IASTBinaryExpression.op_minus:
} t2= getExpressionType(binary.getOperand2());
break; if (SemanticUtil.getUltimateTypeViaTypedefs(t2) instanceof IPointerType) {
case ICPPASTBinaryExpression.op_pmarrow: IType t1 = getExpressionType(binary.getOperand1());
case ICPPASTBinaryExpression.op_pmdot: if (SemanticUtil.getUltimateTypeViaTypedefs(t1) instanceof IPointerType) {
IType type = getExpressionType(((IASTBinaryExpression) expression).getOperand2()); IScope scope = getContainingScope(expression);
if (type instanceof ICPPPointerToMemberType) { try {
try { IBinding[] bs = scope.find(PTRDIFF_T);
result = ((ICPPPointerToMemberType)type).getType(); if (bs.length > 0 && bs[0] instanceof IType) {
} catch (DOMException e) { return (IType) bs[0];
result = e.getProblem(); }
} } catch (DOMException e) {
} else { }
result = new ProblemBinding(binary, IProblemBinding.SEMANTIC_INVALID_TYPE, new char[0]); basicType= new CPPBasicType(IBasicType.t_int, ICPPBasicType.IS_LONG | ICPPBasicType.IS_UNSIGNED);
} basicType.setValue(expression);
break; return basicType;
default: }
result = getExpressionType(((IASTBinaryExpression) expression).getOperand1()); return t1;
} }
break;
if (result instanceof CPPBasicType) { case ICPPASTBinaryExpression.op_pmarrow:
((CPPBasicType)result).setValue(expression); case ICPPASTBinaryExpression.op_pmdot:
IType type = getExpressionType(((IASTBinaryExpression) expression).getOperand2());
if (type instanceof ICPPPointerToMemberType) {
try {
return ((ICPPPointerToMemberType)type).getType();
} catch (DOMException e) {
return e.getProblem();
}
}
return new ProblemBinding(binary, IProblemBinding.SEMANTIC_INVALID_TYPE, new char[0]);
} }
return result; return getExpressionType(((IASTBinaryExpression) expression).getOperand1());
} else if (expression instanceof IASTUnaryExpression) { } else if (expression instanceof IASTUnaryExpression) {
int op = ((IASTUnaryExpression)expression).getOperator(); int op = ((IASTUnaryExpression)expression).getOperator();
if (op == IASTUnaryExpression.op_sizeof) { if (op == IASTUnaryExpression.op_sizeof) {
@ -2047,11 +2050,6 @@ public class CPPVisitor {
return action.getProblems(); return action.getProblems();
} }
/**
* @param unit
* @param binding
* @return
*/
public static IASTName[] getReferences(IASTTranslationUnit tu, IBinding binding) { public static IASTName[] getReferences(IASTTranslationUnit tu, IBinding binding) {
CollectReferencesAction action = new CollectReferencesAction(binding); CollectReferencesAction action = new CollectReferencesAction(binding);
tu.accept(action); tu.accept(action);