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