mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
fix bug 90609 : lookup of names used in friend declaration
This commit is contained in:
parent
52a370c3ae
commit
0c76ed8894
4 changed files with 119 additions and 37 deletions
|
@ -41,39 +41,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
[--Start Example(CPP 3.4.1-10):
|
|
||||||
struct A {
|
|
||||||
typedef int AT;
|
|
||||||
void f1(AT);
|
|
||||||
void f2(float);
|
|
||||||
};
|
|
||||||
struct B {
|
|
||||||
typedef float BT;
|
|
||||||
friend void A::f1(AT); // parameter type is A::AT
|
|
||||||
friend void A::f2(BT); // parameter type is B::BT
|
|
||||||
};
|
|
||||||
--End Example]
|
|
||||||
*/
|
|
||||||
public void test3_4_1s10() { // TODO raised bug 90609
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
buffer.append("struct A {\n"); //$NON-NLS-1$
|
|
||||||
buffer.append("typedef int AT;\n"); //$NON-NLS-1$
|
|
||||||
buffer.append("void f1(AT);\n"); //$NON-NLS-1$
|
|
||||||
buffer.append("void f2(float);\n"); //$NON-NLS-1$
|
|
||||||
buffer.append("};\n"); //$NON-NLS-1$
|
|
||||||
buffer.append("struct B {\n"); //$NON-NLS-1$
|
|
||||||
buffer.append("typedef float BT;\n"); //$NON-NLS-1$
|
|
||||||
buffer.append("friend void A::f1(AT); // parameter type is A::AT\n"); //$NON-NLS-1$
|
|
||||||
buffer.append("friend void A::f2(BT); // parameter type is B::BT\n"); //$NON-NLS-1$
|
|
||||||
buffer.append("};\n"); //$NON-NLS-1$
|
|
||||||
try {
|
|
||||||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
|
||||||
assertTrue(false);
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[--Start Example(CPP 6.4-3):
|
[--Start Example(CPP 6.4-3):
|
||||||
int foo() {
|
int foo() {
|
||||||
|
|
|
@ -447,6 +447,36 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
|
||||||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
[--Start Example(CPP 3.4.1-10):
|
||||||
|
struct A {
|
||||||
|
typedef int AT;
|
||||||
|
void f1(AT);
|
||||||
|
void f2(float);
|
||||||
|
};
|
||||||
|
struct B {
|
||||||
|
typedef float BT;
|
||||||
|
friend void A::f1(AT); // parameter type is A::AT
|
||||||
|
friend void A::f2(BT); // parameter type is B::BT
|
||||||
|
};
|
||||||
|
--End Example]
|
||||||
|
*/
|
||||||
|
public void test3_4_1s10() throws Exception {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
buffer.append("struct A {\n"); //$NON-NLS-1$
|
||||||
|
buffer.append("typedef int AT;\n"); //$NON-NLS-1$
|
||||||
|
buffer.append("void f1(AT);\n"); //$NON-NLS-1$
|
||||||
|
buffer.append("void f2(float);\n"); //$NON-NLS-1$
|
||||||
|
buffer.append("};\n"); //$NON-NLS-1$
|
||||||
|
buffer.append("struct B {\n"); //$NON-NLS-1$
|
||||||
|
buffer.append("typedef float BT;\n"); //$NON-NLS-1$
|
||||||
|
buffer.append("friend void A::f1(AT); // parameter type is A::AT\n"); //$NON-NLS-1$
|
||||||
|
buffer.append("friend void A::f2(BT); // parameter type is B::BT\n"); //$NON-NLS-1$
|
||||||
|
buffer.append("};\n"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[--Start Example(CPP 3.4.2-2):
|
[--Start Example(CPP 3.4.2-2):
|
||||||
namespace NS {
|
namespace NS {
|
||||||
|
@ -12524,12 +12554,12 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
|
||||||
*/
|
*/
|
||||||
public void test8_5s2() throws ParserException { // 90641
|
public void test8_5s2() throws ParserException { // 90641
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
buffer.append( "int z() { ");
|
buffer.append( "int z() { "); //$NON-NLS-1$
|
||||||
buffer.append("int f(int);\n"); //$NON-NLS-1$
|
buffer.append("int f(int);\n"); //$NON-NLS-1$
|
||||||
buffer.append("int a = 2;\n"); //$NON-NLS-1$
|
buffer.append("int a = 2;\n"); //$NON-NLS-1$
|
||||||
buffer.append("int b = f(a);\n"); //$NON-NLS-1$
|
buffer.append("int b = f(a);\n"); //$NON-NLS-1$
|
||||||
buffer.append("int c(b);\n"); //$NON-NLS-1$
|
buffer.append("int c(b);\n"); //$NON-NLS-1$
|
||||||
buffer.append( "}");
|
buffer.append( "}"); //$NON-NLS-1$
|
||||||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4861,4 +4861,32 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
ICPPMethod f = (ICPPMethod) col.getName(3).resolveBinding();
|
ICPPMethod f = (ICPPMethod) col.getName(3).resolveBinding();
|
||||||
assertSame( f, col.getName(6).resolveBinding() );
|
assertSame( f, col.getName(6).resolveBinding() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testBug90609() throws Exception {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
buffer.append("struct A { \n"); //$NON-NLS-1$
|
||||||
|
buffer.append(" typedef int AT; \n"); //$NON-NLS-1$
|
||||||
|
buffer.append(" void f1(AT); \n"); //$NON-NLS-1$
|
||||||
|
buffer.append(" void f2(float); \n"); //$NON-NLS-1$
|
||||||
|
buffer.append("}; \n"); //$NON-NLS-1$
|
||||||
|
buffer.append("struct B { \n"); //$NON-NLS-1$
|
||||||
|
buffer.append(" typedef float BT; \n"); //$NON-NLS-1$
|
||||||
|
buffer.append(" friend void A::f1(AT); \n"); //$NON-NLS-1$
|
||||||
|
buffer.append(" friend void A::f2(BT); \n"); //$NON-NLS-1$
|
||||||
|
buffer.append("}; \n"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP, true, true );
|
||||||
|
CPPNameCollector col = new CPPNameCollector();
|
||||||
|
tu.accept( col );
|
||||||
|
|
||||||
|
ITypedef AT = (ITypedef) col.getName(1).resolveBinding();
|
||||||
|
ICPPMethod f1 = (ICPPMethod) col.getName(2).resolveBinding();
|
||||||
|
ICPPMethod f2 = (ICPPMethod) col.getName(5).resolveBinding();
|
||||||
|
ITypedef BT = (ITypedef) col.getName(8).resolveBinding();
|
||||||
|
|
||||||
|
assertSame( f1, col.getName(11).resolveBinding() );
|
||||||
|
assertSame( AT, col.getName(12).resolveBinding() );
|
||||||
|
assertSame( f2, col.getName(16).resolveBinding() );
|
||||||
|
assertSame( BT, col.getName(17).resolveBinding() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -419,6 +419,47 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean checkAssociatedScopes() {
|
||||||
|
if( astName == null || astName instanceof ICPPASTQualifiedName )
|
||||||
|
return false;
|
||||||
|
IASTNode parent = astName.getParent();
|
||||||
|
if( parent instanceof ICPPASTQualifiedName ){
|
||||||
|
IASTName [] ns = ((ICPPASTQualifiedName)parent).getNames();
|
||||||
|
if( ns[ ns.length - 1] != astName )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return functionCall() && (associated.size() > 0);
|
||||||
|
}
|
||||||
|
public boolean checkClassContainingFriend() {
|
||||||
|
if( astName == null || astName instanceof ICPPASTQualifiedName )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IASTNode p = astName.getParent();
|
||||||
|
ASTNodeProperty prop = null;
|
||||||
|
while( p != null ){
|
||||||
|
prop = p.getPropertyInParent();
|
||||||
|
if( prop == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT || prop == IASTDeclarator.DECLARATOR_NAME )
|
||||||
|
return false;
|
||||||
|
if( p instanceof IASTDeclarator && !(((IASTDeclarator)p).getName() instanceof ICPPASTQualifiedName) )
|
||||||
|
return false;
|
||||||
|
if( p instanceof IASTDeclaration ){
|
||||||
|
if( prop == IASTCompositeTypeSpecifier.MEMBER_DECLARATION ){
|
||||||
|
if( p instanceof IASTSimpleDeclaration ){
|
||||||
|
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTSimpleDeclaration)p).getDeclSpecifier();
|
||||||
|
return declSpec.isFriend();
|
||||||
|
} else if( p instanceof IASTFunctionDefinition ){
|
||||||
|
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTFunctionDefinition)p).getDeclSpecifier();
|
||||||
|
return declSpec.isFriend();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p = p.getParent();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static protected class Cost
|
static protected class Cost
|
||||||
|
@ -586,11 +627,11 @@ public class CPPSemantics {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static IBinding postResolution( IBinding binding, LookupData data ) {
|
private static IBinding postResolution( IBinding binding, LookupData data ) {
|
||||||
if( !(data.astName instanceof ICPPASTQualifiedName) && data.functionCall() ){
|
if( data.checkAssociatedScopes() ){
|
||||||
//3.4.2 argument dependent name lookup, aka Koenig lookup
|
//3.4.2 argument dependent name lookup, aka Koenig lookup
|
||||||
try {
|
try {
|
||||||
IScope scope = (binding != null ) ? binding.getScope() : null;
|
IScope scope = (binding != null ) ? binding.getScope() : null;
|
||||||
if( data.associated.size() > 0 && ( scope == null|| !(scope instanceof ICPPClassScope) ) ){
|
if( scope == null || !(scope instanceof ICPPClassScope) ){
|
||||||
data.ignoreUsingDirectives = true;
|
data.ignoreUsingDirectives = true;
|
||||||
data.forceQualified = true;
|
data.forceQualified = true;
|
||||||
for( int i = 0; i < data.associated.size(); i++ ){
|
for( int i = 0; i < data.associated.size(); i++ ){
|
||||||
|
@ -601,6 +642,22 @@ public class CPPSemantics {
|
||||||
} catch ( DOMException e ) {
|
} catch ( DOMException e ) {
|
||||||
binding = e.getProblem();
|
binding = e.getProblem();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if( binding == null && data.checkClassContainingFriend() ){
|
||||||
|
//3.4.1-10 if we don't find a name used in a friend declaration in the member declaration's class
|
||||||
|
//we should look in the class granting friendship
|
||||||
|
IASTNode parent = data.astName.getParent();
|
||||||
|
while( parent != null && !(parent instanceof ICPPASTCompositeTypeSpecifier) )
|
||||||
|
parent = parent.getParent();
|
||||||
|
if( parent instanceof ICPPASTCompositeTypeSpecifier ){
|
||||||
|
IScope scope = ((ICPPASTCompositeTypeSpecifier)parent).getScope();
|
||||||
|
try {
|
||||||
|
lookup( data, scope );
|
||||||
|
binding = resolveAmbiguities( data, data.astName );
|
||||||
|
} catch( DOMException e ){
|
||||||
|
binding = e.getProblem();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( binding instanceof ICPPClassTemplate ){
|
if( binding instanceof ICPPClassTemplate ){
|
||||||
ASTNodeProperty prop = data.astName.getPropertyInParent();
|
ASTNodeProperty prop = data.astName.getPropertyInParent();
|
||||||
|
|
Loading…
Add table
Reference in a new issue