1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 17:35:35 +02:00

Bug 452416 - Handle variadic functions in variable read/write analysis

Change-Id: Ib28574d3cdc14fc380e6ceb8b2ba4a240b2316c6
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
Nathan Ridge 2015-02-09 03:27:46 -05:00 committed by Gerrit Code Review @ Eclipse.org
parent fd11d42d89
commit 6a87e3014d
3 changed files with 40 additions and 6 deletions

View file

@ -215,4 +215,16 @@ public class VariableReadWriteFlagsTest extends AST2TestBase {
a.assertReadWriteFlags("ap->m()", "ap", READ);
a.assertReadWriteFlags("(*ap).m()", "ap", READ);
}
// void variadic(...);
// void test() {
// int waldo;
// variadic(waldo);
// variadic(&waldo);
// }
public void testVariadicFunctionCall_452416() throws Exception {
AssertionHelper a = getCPPAssertionHelper();
a.assertReadWriteFlags("variadic(waldo)", "waldo", READ);
a.assertReadWriteFlags("variadic(&waldo)", "waldo", READ | WRITE);
}
}

View file

@ -48,6 +48,7 @@ import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
@ -191,14 +192,15 @@ public abstract class VariableReadWriteFlags {
if (functionNameExpression != null) {
final IType type= functionNameExpression.getExpressionType();
if (type instanceof IFunctionType) {
return rwArgumentForFunctionCall((IFunctionType) type, i, indirection);
return rwArgumentForFunctionCall((IFunctionType) type, i, args[i], indirection);
} else if (funcCall instanceof IASTImplicitNameOwner) {
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) funcCall).getImplicitNames();
if (implicitNames.length == 1) {
IASTImplicitName name = implicitNames[0];
IBinding binding = name.resolveBinding();
if (binding instanceof IFunction) {
return rwArgumentForFunctionCall(((IFunction) binding).getType(), i, indirection);
return rwArgumentForFunctionCall(((IFunction) binding).getType(), i,
args[i], indirection);
}
}
}
@ -209,10 +211,29 @@ public abstract class VariableReadWriteFlags {
return READ | WRITE; // Fallback
}
protected int rwArgumentForFunctionCall(IFunctionType type, int parameterIdx, int indirection) {
private IType getArgumentType(IASTInitializerClause argument) {
if (argument instanceof ICPPASTInitializerClause) {
return ((ICPPASTInitializerClause) argument).getEvaluation().getTypeOrFunctionSet(argument);
} else if (argument instanceof IASTExpression) {
return ((IASTExpression) argument).getExpressionType();
}
return null;
}
protected int rwArgumentForFunctionCall(IFunctionType type, int parameterIdx,
IASTInitializerClause argument, int indirection) {
IType[] ptypes= type.getParameterTypes();
IType parameterType = null;
if (ptypes != null && ptypes.length > parameterIdx) {
return rwAssignmentToType(ptypes[parameterIdx], indirection);
parameterType = ptypes[parameterIdx];
} else if (type.takesVarArgs()) {
// Since variadic functions take their arguments by value, synthesize a parameter type
// equal to the argument type.
parameterType = getArgumentType(argument);
}
if (parameterType != null) {
return rwAssignmentToType(parameterType, indirection);
}
return READ | WRITE; // Fallback
}

View file

@ -16,6 +16,7 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
@ -78,9 +79,9 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
if (b instanceof ICPPConstructor) {
final ICPPConstructor ctor = (ICPPConstructor) b;
int idx= 0;
for (IASTNode child : parent.getArguments()) {
for (IASTInitializerClause child : parent.getArguments()) {
if (child == node) {
return rwArgumentForFunctionCall(ctor.getType(), idx, indirection);
return rwArgumentForFunctionCall(ctor.getType(), idx, child, indirection);
}
idx++;
}