diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index fb08acfef5a..86e65f4e085 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -1018,5 +1018,41 @@ public class AST2CPPTests extends AST2BaseTest { assertSame( p_ref, p_decl ); } + public void testBug84266() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append( "struct s { double i; } f(void); \n"); //$NON-NLS-1$ + buffer.append( "struct s f(void){} \n"); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP); + CPPNameCollector col = new CPPNameCollector(); + CPPVisitor.visitTranslationUnit(tu, col); + + assertEquals(col.size(), 7); + + ICompositeType s_ref = (ICompositeType) col.getName(4).resolveBinding(); + ICompositeType s_decl = (ICompositeType) col.getName(0).resolveBinding(); + + assertSame( s_ref, s_decl ); + } + + public void testBug84266_2() throws Exception { + IASTTranslationUnit tu = parse("struct s f(void);", ParserLanguage.CPP); //$NON-NLS-1$ + CPPNameCollector col = new CPPNameCollector(); + CPPVisitor.visitTranslationUnit(tu, col); + + assertEquals(col.size(), 3); + + ICompositeType s = (ICompositeType) col.getName(0).resolveBinding(); + assertNotNull( s ); + + tu = parse("struct s f(void){}", ParserLanguage.CPP); //$NON-NLS-1$ + col = new CPPNameCollector(); + CPPVisitor.visitTranslationUnit(tu, col); + + assertEquals(col.size(), 3); + + s = (ICompositeType) col.getName(0).resolveBinding(); + assertNotNull( s ); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index c0156dbc658..e66464ba54f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -2672,6 +2672,49 @@ public class AST2Tests extends AST2BaseTest { parse( buffer.toString(), ParserLanguage.C ); } + public void testBug84266() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append( "struct s { double i; } f(void); \n"); //$NON-NLS-1$ + buffer.append( "struct s f(void){} \n"); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.C); + CNameCollector col = new CNameCollector(); + CVisitor.visitTranslationUnit(tu, col); + + assertEquals(col.size(), 7); + + ICompositeType s_ref = (ICompositeType) col.getName(4).resolveBinding(); + ICompositeType s_decl = (ICompositeType) col.getName(0).resolveBinding(); + + assertSame( s_ref, s_decl ); + CVisitor.clearBindings( tu ); + + s_decl = (ICompositeType) col.getName(0).resolveBinding(); + s_ref = (ICompositeType) col.getName(4).resolveBinding(); + + assertSame( s_ref, s_decl ); + } + + public void testBug84266_2() throws Exception { + IASTTranslationUnit tu = parse("struct s f(void);", ParserLanguage.C); //$NON-NLS-1$ + CNameCollector col = new CNameCollector(); + CVisitor.visitTranslationUnit(tu, col); + + assertEquals(col.size(), 3); + + ICompositeType s = (ICompositeType) col.getName(0).resolveBinding(); + assertNotNull( s ); + + tu = parse("struct s f(void){}", ParserLanguage.C); //$NON-NLS-1$ + col = new CNameCollector(); + CVisitor.visitTranslationUnit(tu, col); + + assertEquals(col.size(), 3); + + s = (ICompositeType) col.getName(0).resolveBinding(); + assertNotNull( s ); + } + public void testBug84250() throws Exception { assertTrue( ((IASTDeclarationStatement) ((IASTCompoundStatement) ((IASTFunctionDefinition) parse( "void f() { int (*p) [2]; }", ParserLanguage.C ).getDeclarations()[0]).getBody()).getStatements()[0]).getDeclaration() instanceof IASTSimpleDeclaration ); //$NON-NLS-1$ } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java index 133d96e26ac..879dc7e3501 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java @@ -1652,7 +1652,7 @@ public class CompleteParser2Tests extends TestCase { assertEquals( col.size(), 2 ); - IProblemBinding blah = (IProblemBinding) col.getName(0).resolveBinding(); + ICPPClassType blah = (ICPPClassType) col.getName(0).resolveBinding(); ITypedef sb = (ITypedef) col.getName(1).resolveBinding(); assertSame( sb.getType(), blah ); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index e6ad2b91fb1..9555be8c4af 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -562,30 +562,31 @@ public class CVisitor { } private static IBinding createBinding( ICASTElaboratedTypeSpecifier elabTypeSpec ){ IASTNode parent = elabTypeSpec.getParent(); - if( parent instanceof IASTSimpleDeclaration ){ - IASTSimpleDeclaration declaration = (IASTSimpleDeclaration) parent; - if( declaration.getDeclarators().length == 0 ){ - //forward declaration - IBinding binding = resolveBinding( elabTypeSpec, CURRENT_SCOPE | TAGS ); - if( binding == null ){ - if( elabTypeSpec.getKind() == IASTElaboratedTypeSpecifier.k_enum ){ - binding = new CEnumeration( elabTypeSpec.getName() ); - } else { - binding = new CStructure( elabTypeSpec ); - } - - try { - ((ICScope) binding.getScope()).addBinding( binding ); - } catch ( DOMException e ) { - } - } else { - if( binding instanceof CEnumeration ){ - ((CEnumeration)binding).addDeclaration( elabTypeSpec.getName() ); - } - } - return binding; - } - return resolveBinding( elabTypeSpec, COMPLETE | TAGS ); + if( parent instanceof IASTDeclaration ){ + int bits = TAGS; + if( parent instanceof IASTSimpleDeclaration && ((IASTSimpleDeclaration)parent).getDeclarators().length == 0 ){ + bits |= CURRENT_SCOPE; + } + + IBinding binding = resolveBinding( elabTypeSpec, bits ); + if( binding != null ){ + if( binding instanceof CEnumeration ){ + ((CEnumeration)binding).addDeclaration( elabTypeSpec.getName() ); + } + } else { + if( elabTypeSpec.getKind() == IASTElaboratedTypeSpecifier.k_enum ){ + binding = new CEnumeration( elabTypeSpec.getName() ); + } else { + binding = new CStructure( elabTypeSpec ); + } + + try { + ((ICScope) binding.getScope()).addBinding( binding ); + } catch ( DOMException e ) { + } + } + + return binding; } else if( parent instanceof IASTTypeId || parent instanceof IASTParameterDeclaration ){ IASTNode blockItem = getContainingBlockItem( parent ); return findBinding( blockItem, elabTypeSpec.getName(), COMPLETE | TAGS ); @@ -977,7 +978,7 @@ public class CVisitor { public static IScope getContainingScope( IASTDeclSpecifier compTypeSpec ){ IASTNode parent = compTypeSpec.getParent(); - return getContainingScope( (IASTSimpleDeclaration) parent ); + return getContainingScope( parent ); } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java index e9222890366..d3f747af536 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java @@ -241,19 +241,45 @@ public class CPPVisitor { private static IBinding createBinding( ICPPASTElaboratedTypeSpecifier elabType ){ IASTNode parent = elabType.getParent(); + IBinding binding = null; + boolean mustBeSimple = true; if( parent instanceof IASTSimpleDeclaration ){ IASTDeclarator [] dtors = ((IASTSimpleDeclaration)parent).getDeclarators(); if( dtors.length > 0 ){ - return CPPSemantics.resolveBinding( elabType.getName() ); + binding = CPPSemantics.resolveBinding( elabType.getName() ); + } else { + mustBeSimple = false; } - } else if( parent instanceof IASTParameterDeclaration ){ - return CPPSemantics.resolveBinding( elabType.getName() ); - } else if( parent instanceof IASTTypeId ){ - return CPPSemantics.resolveBinding( elabType.getName() ); + } else if( parent instanceof IASTParameterDeclaration || + parent instanceof IASTDeclaration || + parent instanceof IASTTypeId ) + { + binding = CPPSemantics.resolveBinding( elabType.getName() ); } + if( binding != null && + (!(binding instanceof IProblemBinding) ||((IProblemBinding)binding).getID() != IProblemBinding.SEMANTIC_NAME_NOT_FOUND) ) + { + return binding; + } + + //7.1.5.3-2 ... If name lookup does not find a declaration for the name, the elaborated-type-specifier is ill-formed + //unless it is of the simple form class-key identifier + if( mustBeSimple && elabType.getName() instanceof ICPPASTQualifiedName ) + return binding; + ICPPScope scope = (ICPPScope) getContainingScope( elabType ); - IBinding binding; + + if( mustBeSimple ){ + //3.3.1-5 ... the identifier is declared in the smallest non-class non-function-prototype scope that contains + //the declaration + while( scope instanceof ICPPClassScope || scope instanceof ICPPFunctionScope ){ + try { + scope = (ICPPScope) scope.getParent(); + } catch (DOMException e1) { + } + } + } try { binding = scope.getBinding( elabType.getName() ); if( binding == null ){