1
0
Fork 0
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:
Andrew Niefer 2005-06-28 17:59:27 +00:00
parent 52a370c3ae
commit 0c76ed8894
4 changed files with 119 additions and 37 deletions

View file

@ -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):
int foo() {

View file

@ -447,6 +447,36 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
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):
namespace NS {
@ -12524,12 +12554,12 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
*/
public void test8_5s2() throws ParserException { // 90641
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 a = 2;\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( "}");
buffer.append( "}"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
}

View file

@ -4861,4 +4861,32 @@ public class AST2CPPTests extends AST2BaseTest {
ICPPMethod f = (ICPPMethod) col.getName(3).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() );
}
}

View file

@ -419,6 +419,47 @@ public class CPPSemantics {
}
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
@ -586,11 +627,11 @@ public class CPPSemantics {
* @return
*/
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
try {
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.forceQualified = true;
for( int i = 0; i < data.associated.size(); i++ ){
@ -601,6 +642,22 @@ public class CPPSemantics {
} catch ( DOMException e ) {
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 ){
ASTNodeProperty prop = data.astName.getPropertyInParent();