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:
parent
820b901b69
commit
e6b392ffbc
4 changed files with 109 additions and 21 deletions
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue