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:
parent
ff8baa2754
commit
424c2898fe
14 changed files with 80 additions and 57 deletions
|
@ -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);
|
||||
|
|
|
@ -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(){}
|
||||
// };
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue