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

Bug 438114 - Friend function declaration is not reconciled with other

declarations
This commit is contained in:
Sergey Prigogin 2014-06-24 20:20:54 -07:00
parent 820b901b69
commit e6b392ffbc
4 changed files with 109 additions and 21 deletions

View file

@ -6891,6 +6891,27 @@ public class AST2CPPTests extends AST2TestBase {
assertSame(g1, g2); assertSame(g1, g2);
} }
// template <typename T>
// class A {
// template <typename U>
// friend int func(int i);
// };
//
// template <typename U>
// int func(int i = 0);
//
// template <typename U>
// int func(int i) { return i; }
public void testFriendFunction_438114() throws Exception {
BindingAssertionHelper bh = getAssertionHelper();
ICPPFunction f1= bh.assertNonProblemOnFirstIdentifier("func(int i);");
ICPPFunction f2= bh.assertNonProblemOnFirstIdentifier("func(int i = 0);");
ICPPFunction f3= bh.assertNonProblemOnFirstIdentifier("func(int i) {");
assertSame(f1, f2);
assertSame(f2, f3);
assertEquals(0, f1.getRequiredArgumentCount());
}
// class A { // class A {
// public: // public:
// void foo() const volatile; // void foo() const volatile;

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2013 IBM Corporation and others. * Copyright (c) 2004, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -29,7 +29,6 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement; import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTTypeId;
@ -43,6 +42,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
@ -169,23 +169,46 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
@Override @Override
public ICPPParameter[] getParameters() { public ICPPParameter[] getParameters() {
IASTStandardFunctionDeclarator dtor = getPreferredDtor(); ICPPASTFunctionDeclarator declarator = getDefinition();
if (dtor == null) { IASTDeclarator[] dtors = getDeclarations();
if (dtors != null) {
// In case of multiple function declarations we select the one with the most
// default parameter values.
int defaultValuePosition = -1;
for (IASTDeclarator dtor : dtors) {
if (dtor instanceof ICPPASTFunctionDeclarator) {
if (declarator == null) {
declarator = (ICPPASTFunctionDeclarator) dtor;
} else {
ICPPASTFunctionDeclarator contender = (ICPPASTFunctionDeclarator) dtor;
if (defaultValuePosition < 0)
defaultValuePosition = findFirstDefaultValue(declarator.getParameters());
int pos = findFirstDefaultValue(contender.getParameters());
if (pos < defaultValuePosition) {
declarator = contender;
defaultValuePosition = pos;
}
}
}
}
}
if (declarator == null) {
return CPPBuiltinParameter.createParameterList(getType()); return CPPBuiltinParameter.createParameterList(getType());
} }
IASTParameterDeclaration[] params = dtor.getParameters(); IASTParameterDeclaration[] params = declarator.getParameters();
int size = params.length; int size = params.length;
ICPPParameter[] result = new ICPPParameter[size]; ICPPParameter[] result = new ICPPParameter[size];
if (size > 0) { if (size > 0) {
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
IASTParameterDeclaration p = params[i]; IASTParameterDeclaration param = params[i];
final IASTName name = getParamName(p); final IASTName name = getParamName(param);
final IBinding binding= name.resolveBinding(); final IBinding binding= name.resolveBinding();
if (binding instanceof ICPPParameter) { if (binding instanceof ICPPParameter) {
result[i]= (ICPPParameter) binding; result[i]= (ICPPParameter) binding;
} else { } else {
result[i] = new CPPParameter.CPPParameterProblem(p, result[i] = new CPPParameter.CPPParameterProblem(
IProblemBinding.SEMANTIC_INVALID_TYPE, name.toCharArray()); param, IProblemBinding.SEMANTIC_INVALID_TYPE, name.toCharArray());
} }
} }
@ -195,6 +218,18 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
return result; return result;
} }
/**
* Returns the position of the first parameter that has a default value.
* If none of the parameters has a default value, return the number of parameters.
*/
static int findFirstDefaultValue(ICPPASTParameterDeclaration[] parameters) {
for (int i = parameters.length; --i >= 0;) {
if (parameters[i].getDeclarator().getInitializer() == null)
return i + 1;
}
return 0;
}
@Override @Override
public IScope getFunctionScope() { public IScope getFunctionScope() {
resolveAllDeclarations(); resolveAllDeclarations();
@ -595,10 +630,10 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
if (dtors != null) { if (dtors != null) {
for (IASTDeclarator declarator : dtors) { for (IASTDeclarator declarator : dtors) {
if (declarator instanceof ICPPASTFunctionDeclarator) if (declarator instanceof ICPPASTFunctionDeclarator)
return (ICPPASTFunctionDeclarator) declarator; return (ICPPASTFunctionDeclarator) declarator;
} }
} }
return null; return dtor;
} }
@Override @Override

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2005, 2012 IBM Corporation and others. * Copyright (c) 2005, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -46,7 +46,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/** /**
* Implementation of function templates * Implementation of function templates.
*/ */
public class CPPFunctionTemplate extends CPPTemplateDefinition public class CPPFunctionTemplate extends CPPTemplateDefinition
implements ICPPFunctionTemplate, ICPPInternalFunction { implements ICPPFunctionTemplate, ICPPInternalFunction {
@ -99,23 +99,51 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition
@Override @Override
public ICPPParameter[] getParameters() { public ICPPParameter[] getParameters() {
ICPPASTFunctionDeclarator fdecl= getFirstFunctionDtor(); ICPPASTFunctionDeclarator declarator= null;
if (fdecl != null) { IASTDeclarator dtor= getDeclaratorByName(getDefinition());
IASTParameterDeclaration[] params = fdecl.getParameters(); if (dtor instanceof ICPPASTFunctionDeclarator)
declarator = (ICPPASTFunctionDeclarator) dtor;
IASTNode[] decls = getDeclarations();
if (decls != null) {
// In case of multiple function declarations we select the one with the most
// default parameter values.
int defaultValuePosition = -1;
for (IASTNode decl : decls) {
dtor= getDeclaratorByName(decl);
if (dtor instanceof ICPPASTFunctionDeclarator) {
if (declarator == null) {
declarator = (ICPPASTFunctionDeclarator) dtor;
} else {
ICPPASTFunctionDeclarator contender = (ICPPASTFunctionDeclarator) dtor;
if (defaultValuePosition < 0)
defaultValuePosition = CPPFunction.findFirstDefaultValue(declarator.getParameters());
int pos = CPPFunction.findFirstDefaultValue(contender.getParameters());
if (pos < defaultValuePosition) {
declarator = contender;
defaultValuePosition = pos;
}
}
}
}
}
if (declarator != null) {
IASTParameterDeclaration[] params = declarator.getParameters();
int size = params.length; int size = params.length;
if (size == 0) { if (size == 0) {
return ICPPParameter.EMPTY_CPPPARAMETER_ARRAY; return ICPPParameter.EMPTY_CPPPARAMETER_ARRAY;
} }
ICPPParameter[] result = new ICPPParameter[size]; ICPPParameter[] result = new ICPPParameter[size];
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
IASTParameterDeclaration p = params[i]; IASTParameterDeclaration param = params[i];
final IASTName pname = ASTQueries.findInnermostDeclarator(p.getDeclarator()).getName(); final IASTName pname = ASTQueries.findInnermostDeclarator(param.getDeclarator()).getName();
final IBinding binding= pname.resolveBinding(); final IBinding binding= pname.resolveBinding();
if (binding instanceof ICPPParameter) { if (binding instanceof ICPPParameter) {
result[i]= (ICPPParameter) binding; result[i]= (ICPPParameter) binding;
} else { } else {
result[i] = new CPPParameter.CPPParameterProblem(p, result[i] = new CPPParameter.CPPParameterProblem(
IProblemBinding.SEMANTIC_INVALID_TYPE, pname.toCharArray()); param, IProblemBinding.SEMANTIC_INVALID_TYPE, pname.toCharArray());
} }
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2013 IBM Corporation and others. * Copyright (c) 2004, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -171,6 +171,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; 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.ProblemType;
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator; import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
@ -896,6 +897,9 @@ public class CPPVisitor extends ASTQueries {
: new CPPFunction(typeRelevantDtor); : new CPPFunction(typeRelevantDtor);
} }
binding= CPPSemantics.checkDeclSpecifier(binding, name, parent); binding= CPPSemantics.checkDeclSpecifier(binding, name, parent);
if (isFriendDecl && scope instanceof IASTInternalScope) {
((IASTInternalScope) scope).addBinding(binding);
}
} }
return binding; return binding;