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):
|
||||
int foo() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue