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);
}
// 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 {
// public:
// 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
* are made available under the terms of the Eclipse Public License v1.0
* 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.IASTReturnStatement;
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.IASTTranslationUnit;
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.ICPPASTFunctionDefinition;
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.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
@ -169,23 +169,46 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
@Override
public ICPPParameter[] getParameters() {
IASTStandardFunctionDeclarator dtor = getPreferredDtor();
if (dtor == null) {
ICPPASTFunctionDeclarator declarator = getDefinition();
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());
}
IASTParameterDeclaration[] params = dtor.getParameters();
IASTParameterDeclaration[] params = declarator.getParameters();
int size = params.length;
ICPPParameter[] result = new ICPPParameter[size];
if (size > 0) {
for (int i = 0; i < size; i++) {
IASTParameterDeclaration p = params[i];
final IASTName name = getParamName(p);
IASTParameterDeclaration param = params[i];
final IASTName name = getParamName(param);
final IBinding binding= name.resolveBinding();
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(
param, IProblemBinding.SEMANTIC_INVALID_TYPE, name.toCharArray());
}
}
@ -195,6 +218,18 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
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
public IScope getFunctionScope() {
resolveAllDeclarations();
@ -595,10 +630,10 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
if (dtors != null) {
for (IASTDeclarator declarator : dtors) {
if (declarator instanceof ICPPASTFunctionDeclarator)
return (ICPPASTFunctionDeclarator) declarator;
return (ICPPASTFunctionDeclarator) declarator;
}
}
return null;
return dtor;
}
@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
* are made available under the terms of the Eclipse Public License v1.0
* 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;
/**
* Implementation of function templates
* Implementation of function templates.
*/
public class CPPFunctionTemplate extends CPPTemplateDefinition
implements ICPPFunctionTemplate, ICPPInternalFunction {
@ -99,23 +99,51 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition
@Override
public ICPPParameter[] getParameters() {
ICPPASTFunctionDeclarator fdecl= getFirstFunctionDtor();
if (fdecl != null) {
IASTParameterDeclaration[] params = fdecl.getParameters();
ICPPASTFunctionDeclarator declarator= null;
IASTDeclarator dtor= getDeclaratorByName(getDefinition());
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;
if (size == 0) {
return ICPPParameter.EMPTY_CPPPARAMETER_ARRAY;
}
ICPPParameter[] result = new ICPPParameter[size];
for (int i = 0; i < size; i++) {
IASTParameterDeclaration p = params[i];
final IASTName pname = ASTQueries.findInnermostDeclarator(p.getDeclarator()).getName();
IASTParameterDeclaration param = params[i];
final IASTName pname = ASTQueries.findInnermostDeclarator(param.getDeclarator()).getName();
final IBinding binding= pname.resolveBinding();
if (binding instanceof ICPPParameter) {
result[i]= (ICPPParameter) binding;
} else {
result[i] = new CPPParameter.CPPParameterProblem(p,
IProblemBinding.SEMANTIC_INVALID_TYPE, pname.toCharArray());
result[i] = new CPPParameter.CPPParameterProblem(
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
* are made available under the terms of the Eclipse Public License v1.0
* 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.ASTQueries;
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.ProblemType;
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
@ -896,6 +897,9 @@ public class CPPVisitor extends ASTQueries {
: new CPPFunction(typeRelevantDtor);
}
binding= CPPSemantics.checkDeclSpecifier(binding, name, parent);
if (isFriendDecl && scope instanceof IASTInternalScope) {
((IASTInternalScope) scope).addBinding(binding);
}
}
return binding;