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

Bug 423127 - Template resolution gets confused by "void" in a parameter

list

Change-Id: I6d2510ce7f1c8007da7121855bc4870e4a57d15d
Reviewed-on: https://git.eclipse.org/r/19355
Tested-by: Hudson CI
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
Sergey Prigogin 2013-12-04 19:47:59 -08:00
parent ff8baa2754
commit 424c2898fe
14 changed files with 80 additions and 57 deletions

View file

@ -1275,17 +1275,13 @@ public class AST2CPPTests extends AST2TestBase {
ICPPConstructor[] ctors = A.getConstructors();
assertNotNull(ctors);
assertEquals(ctors.length, 2);
assertEquals(2, ctors.length);
assertEquals(ctors[0].getParameters().length, 1);
assertEquals(0, ctors[0].getParameters().length);
IType t = ctors[0].getParameters()[0].getType();
assertTrue(t instanceof IBasicType);
assertEquals(((IBasicType) t).getType(), IBasicType.t_void);
assertEquals(1, ctors[1].getParameters().length);
assertEquals(ctors[1].getParameters().length, 1);
t = ctors[1].getParameters()[0].getType();
IType t = ctors[1].getParameters()[0].getType();
assertTrue(t instanceof ICPPReferenceType);
assertTrue(((ICPPReferenceType) t).getType() instanceof IQualifierType);
IQualifierType qt = (IQualifierType) ((ICPPReferenceType) t).getType();
@ -1305,8 +1301,8 @@ public class AST2CPPTests extends AST2TestBase {
assertNotNull(ctors);
assertEquals(ctors.length, 2);
assertEquals(ctors[0].getParameters().length, 1);
assertEquals(ctors[1].getParameters().length, 1);
assertEquals(0, ctors[0].getParameters().length);
assertEquals(1, ctors[1].getParameters().length);
IType t = ctors[1].getParameters()[0].getType();
assertTrue(t instanceof ICPPReferenceType);

View file

@ -5617,6 +5617,23 @@ public class AST2TemplateTests extends AST2TestBase {
parseAndCheckBindings();
}
// template <class T1, class T2, class U>
// void A(T1* obj, void (T2::*member)(U));
//
// template <class T1, class T2>
// void A(T1* obj, void (T2::*member)());
//
// class B {
// void m1(void);
//
// void m2() {
// A(this, &B::m1);
// }
// };
public void testFunctionWithVoidParamInTypeDeduction_423127() throws Exception {
parseAndCheckBindings();
}
// template<typename T, unsigned length> struct Templ {
// Templ(){}
// };

View file

@ -22,6 +22,7 @@ import java.io.IOException;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.EScopeKind;
import org.eclipse.cdt.core.dom.ast.ExpansionOverlapsBoundaryException;
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
@ -41,7 +42,6 @@ import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
@ -2288,10 +2288,8 @@ public class AST2Tests extends AST2TestBase {
assertTrue(gt_2 instanceof IFunctionType);
IType gt_ret = ((IFunctionType) gt_2).getReturnType();
assertTrue(gt_ret instanceof IBasicType);
assertEquals(((IBasicType) gt_ret).getType(), IBasicType.t_int);
IType gt_parm = ((IFunctionType) gt_2).getParameterTypes()[0];
assertTrue(gt_parm instanceof IBasicType);
assertEquals(((IBasicType) gt_parm).getType(), IBasicType.t_void);
assertEquals(((IBasicType) gt_ret).getKind(), IBasicType.Kind.eInt);
assertEquals(0, ((IFunctionType) gt_2).getParameterTypes().length);
// test tu.getDeclarationsInAST(IBinding)
assertTrue(def.getDeclarator() instanceof IASTStandardFunctionDeclarator);
@ -4970,31 +4968,24 @@ public class AST2Tests extends AST2TestBase {
}
// typedef void VOID;
// VOID func(VOID) {
// VOID func(void) {
// }
public void testTypedefVoid_221567() throws Exception {
String code= getAboveComment();
for (ParserLanguage lang: ParserLanguage.values()) {
BindingAssertionHelper ba= new BindingAssertionHelper(code, lang);
ITypedef td= ba.assertNonProblem("VOID;", 4, ITypedef.class);
IBinding ref= ba.assertNonProblem("VOID)", 4);
assertSame(td, ref);
IFunction func= ba.assertNonProblem("func", 4, IFunction.class);
IFunctionType ft= func.getType();
IType rt= ft.getReturnType();
IType[] pts= ft.getParameterTypes();
assertEquals(1, pts.length);
IType pt = pts[0];
assertEquals(0, pts.length);
assertInstance(rt, ITypedef.class);
assertInstance(pt, ITypedef.class);
rt= ((ITypedef) rt).getType();
pt= ((ITypedef) pt).getType();
assertTrue(rt instanceof IBasicType);
assertEquals(IBasicType.t_void, ((IBasicType) rt).getType());
assertTrue(pt instanceof IBasicType);
assertEquals(IBasicType.t_void, ((IBasicType) pt).getType());
assertEquals(IBasicType.Kind.eVoid, ((IBasicType) rt).getKind());
}
}

View file

@ -417,8 +417,7 @@ public class CompleteParser2Tests extends BaseTestCase {
IFunction foo = (IFunction) col.getName(0).resolveBinding();
IParameter p = (IParameter) col.getName(1).resolveBinding();
assertEquals(foo.getParameters().length, 1);
assertSame(foo.getParameters()[0], p);
assertEquals(0, foo.getParameters().length);
assertSame(p.getScope(), foo.getFunctionScope());
}

View file

@ -70,11 +70,10 @@ public class IndexCBindingResolutionBugs extends IndexBindingResolutionTestBase
assertTrue(b0 instanceof IFunction);
IFunction f0 = (IFunction) b0;
IParameter[] params= f0.getParameters();
assertEquals(1, params.length);
IType param= params[0].getType();
assertTrue(param instanceof IBasicType);
assertEquals(0, params.length);
IType returnType= f0.getType().getReturnType();
assertTrue(returnType instanceof IBasicType);
assertEquals(IBasicType.Kind.eVoid, ((IBasicType) returnType).getKind());
}
// void func1(void);

View file

@ -542,7 +542,7 @@ public class IndexUpdateTests extends IndexTestBase {
new String[] {IMPLICIT, PUBLIC});
updateFile();
checkImplicitMethods("MyClass",
null, // no default constructor, because we declared the copy constr.
null, // no default constructor, because we declared the copy constructor.
new String[] {EXPLICIT, PRIVATE},
new String[] {IMPLICIT, PUBLIC});
updateFile();
@ -563,7 +563,7 @@ public class IndexUpdateTests extends IndexTestBase {
final char[] nchars = name.toCharArray();
final String refType = name + " &";
final String constRefType = "const " + refType;
IIndexBinding[] ctors= fIndex.findBindings(new char[][]{nchars, nchars}, IndexFilter.ALL_DECLARED_OR_IMPLICIT, npm());
IIndexBinding[] ctors= fIndex.findBindings(new char[][] {nchars, nchars}, IndexFilter.ALL_DECLARED_OR_IMPLICIT, npm());
int count= 0;
for (int i = 0; i < ctors.length; i++) {
@ -574,13 +574,13 @@ public class IndexUpdateTests extends IndexTestBase {
}
assertEquals(m1 == null ? 1 : 2, count);
final IType[] parameterTypes = ((ICPPConstructor) ctors[0]).getType().getParameterTypes();
if (parameterTypes.length!=1 || !(parameterTypes[0] instanceof ICPPReferenceType)) {
if (parameterTypes.length != 1 || !(parameterTypes[0] instanceof ICPPReferenceType)) {
IIndexBinding h= ctors[0]; ctors[0]= ctors[1]; ctors[1]= h;
}
if (m1 != null) {
checkCppConstructor((ICPPConstructor) ctors[1], new String[]{"", "void"}, m1);
checkCppConstructor((ICPPConstructor) ctors[1], new String[] {""}, m1);
}
checkCppConstructor((ICPPConstructor) ctors[0], new String[]{"", constRefType}, m2);
checkCppConstructor((ICPPConstructor) ctors[0], new String[] {"", constRefType}, m2);
IIndexBinding[] assignmentOps= fIndex.findBindings(
new char[][] {nchars, "operator =".toCharArray() }, IndexFilter.ALL_DECLARED_OR_IMPLICIT, npm());

View file

@ -459,7 +459,9 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
private void function(String returnType, String name, String... parameterTypes) {
int len = parameterTypes.length;
boolean varargs= len > 0 && parameterTypes[len-1].equals("...");
if (len == 1 && parameterTypes[0].equals("void"))
len--;
boolean varargs= len > 0 && parameterTypes[len - 1].equals("...");
if (varargs)
len--;
@ -473,9 +475,10 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
IType rt = toType(returnType);
IFunctionType ft = fCpp ? new CPPFunctionType(rt, pTypes) : new CFunctionType(rt, pTypes);
IBinding b = fCpp ? new CPPImplicitFunction(toCharArray(name), fScope,
(ICPPFunctionType) ft, (ICPPParameter[]) theParms, varargs)
: new CImplicitFunction(toCharArray(name), fScope, ft, theParms, varargs);
IBinding b = fCpp ?
new CPPImplicitFunction(toCharArray(name), fScope, (ICPPFunctionType) ft,
(ICPPParameter[]) theParms, varargs) :
new CImplicitFunction(toCharArray(name), fScope, ft, theParms, varargs);
fBindingList.add(b);
}

View file

@ -37,6 +37,7 @@ import org.eclipse.cdt.core.parser.util.AttributeUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.core.runtime.PlatformObject;
/**
@ -130,6 +131,9 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
result[i] = (IParameter) ASTQueries.findInnermostDeclarator(p.getDeclarator())
.getName().resolveBinding();
}
if (result.length == 1 && SemanticUtil.isVoidType(result[0].getType()))
return IParameter.EMPTY_PARAMETER_ARRAY;
}
return result;
}

View file

@ -103,6 +103,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.cdt.internal.core.parser.util.ContentAssistMatcherFactory;
/**
@ -1375,6 +1376,9 @@ public class CVisitor extends ASTQueries {
for (int i = 0; i < parms.length; i++) {
parmTypes[i] = createType(parms[i].getDeclarator());
}
if (parmTypes.length == 1 && SemanticUtil.isVoidType(parmTypes[0]))
return IType.EMPTY_TYPE_ARRAY; // f(void) is the same as f()
return parmTypes;
} else if (decltor instanceof ICASTKnRFunctionDeclarator) {
IASTName parms[] = ((ICASTKnRFunctionDeclarator) decltor).getParameterNames();

View file

@ -15,6 +15,7 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter.EMPTY_CPPPARAMETER_ARRAY;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
@ -102,7 +103,6 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
}
char[] className = name.getLookupKey();
ICPPParameter[] voidPs = new ICPPParameter[] { new CPPParameter(CPPSemantics.VOID_TYPE, 0) };
IType pType = new CPPReferenceType(SemanticUtil.constQualify(clsType), false);
ICPPParameter[] ps = new ICPPParameter[] { new CPPParameter(pType, 0) };
@ -111,22 +111,21 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
implicits= new ICPPMethod[ia.getImplicitsToDeclareCount()];
if (!ia.hasUserDeclaredConstructor()) {
//default constructor: A(void)
ICPPMethod m = new CPPImplicitConstructor(this, className, voidPs);
// Default constructor: A(void)
ICPPMethod m = new CPPImplicitConstructor(this, className, EMPTY_CPPPARAMETER_ARRAY);
implicits[i++] = m;
addBinding(m);
}
if (!ia.hasUserDeclaredCopyConstructor()) {
//copy constructor: A(const A &)
// Copy constructor: A(const A &)
ICPPMethod m = new CPPImplicitConstructor(this, className, ps);
implicits[i++] = m;
addBinding(m);
}
if (!ia.hasUserDeclaredCopyAssignmentOperator()) {
//copy assignment operator: A& operator = (const A &)
// Copy assignment operator: A& operator = (const A &)
IType refType = new CPPReferenceType(clsType, false);
ICPPFunctionType ft= CPPVisitor.createImplicitFunctionType(refType, ps, false, false);
ICPPMethod m = new CPPImplicitMethod(this, OverloadableOperator.ASSIGN.toCharArray(), ft, ps);
@ -135,10 +134,10 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
}
if (!ia.hasUserDeclaredDestructor()) {
//destructor: ~A()
ICPPFunctionType ft= CPPVisitor.createImplicitFunctionType(new CPPBasicType(Kind.eUnspecified, 0), voidPs, false, false);
// Destructor: ~A()
ICPPFunctionType ft= CPPVisitor.createImplicitFunctionType(new CPPBasicType(Kind.eUnspecified, 0), EMPTY_CPPPARAMETER_ARRAY, false, false);
char[] dtorName = CharArrayUtils.concat("~".toCharArray(), className); //$NON-NLS-1$
ICPPMethod m = new CPPImplicitMethod(this, dtorName, ft, voidPs);
ICPPMethod m = new CPPImplicitMethod(this, dtorName, ft, EMPTY_CPPPARAMETER_ARRAY);
implicits[i++] = m;
addBinding(m);
}

View file

@ -184,10 +184,13 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
if (binding instanceof ICPPParameter) {
result[i]= (ICPPParameter) binding;
} else {
result[i] = new CPPParameter.CPPParameterProblem(p, IProblemBinding.SEMANTIC_INVALID_TYPE,
name.toCharArray());
result[i] = new CPPParameter.CPPParameterProblem(p,
IProblemBinding.SEMANTIC_INVALID_TYPE, name.toCharArray());
}
}
if (result.length == 1 && SemanticUtil.isVoidType(result[0].getType()))
return ICPPParameter.EMPTY_CPPPARAMETER_ARRAY; // f(void) is the same as f()
}
return result;
}
@ -609,10 +612,10 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
final ICPPParameter p = pars[i];
if (p.hasDefaultValue() || p.isParameterPack()) {
result--;
} else {
if (pars.length == 1 && SemanticUtil.isVoidType(p.getType())) {
return 0;
}
// } else {
// if (pars.length == 1 && SemanticUtil.isVoidType(p.getType())) {
// return 0;
// }
}
}
return result;

View file

@ -43,6 +43,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/**
* Implementation of function templates
@ -117,6 +118,9 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition
IProblemBinding.SEMANTIC_INVALID_TYPE, pname.toCharArray());
}
}
if (result.length == 1 && SemanticUtil.isVoidType(result[0].getType()))
return ICPPParameter.EMPTY_CPPPARAMETER_ARRAY; // f(void) is the same as f()
return result;
}
return CPPBuiltinParameter.createParameterList(getType());

View file

@ -6,8 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -26,7 +26,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
public class CPPImplicitConstructor extends CPPImplicitMethod implements ICPPConstructor {
public CPPImplicitConstructor(ICPPClassScope scope, char[] name, ICPPParameter[] params) {
super( scope, name, createFunctionType(scope, params), params );
super(scope, name, createFunctionType(scope, params), params);
}
private static ICPPFunctionType createFunctionType(ICPPClassScope scope, IParameter[] params) {

View file

@ -1837,6 +1837,10 @@ public class CPPVisitor extends ASTQueries {
for (int i = 0; i < params.length; i++) {
pTypes[i]= createType(params[i], true);
}
if (pTypes.length == 1 && SemanticUtil.isVoidType(pTypes[0])) {
return IType.EMPTY_TYPE_ARRAY; // f(void) is the same as f().
}
return pTypes;
}