From 6a87e3014d59fed7a5515b561249d0a0033cff41 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Mon, 9 Feb 2015 03:27:46 -0500 Subject: [PATCH] Bug 452416 - Handle variadic functions in variable read/write analysis Change-Id: Ib28574d3cdc14fc380e6ceb8b2ba4a240b2316c6 Signed-off-by: Nathan Ridge --- .../ast2/VariableReadWriteFlagsTest.java | 12 ++++++++ .../dom/parser/VariableReadWriteFlags.java | 29 ++++++++++++++++--- .../semantics/CPPVariableReadWriteFlags.java | 5 ++-- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/VariableReadWriteFlagsTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/VariableReadWriteFlagsTest.java index 3fdf112e2fc..156b8874eaf 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/VariableReadWriteFlagsTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/VariableReadWriteFlagsTest.java @@ -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); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java index b32d1f97e6a..3243f436ffb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java @@ -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 } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java index 1961e9bb877..206b5908f96 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java @@ -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++; }