From 94d86b038e4e066effca9b5216a7cbc52135506a Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Fri, 8 Apr 2005 22:35:30 +0000 Subject: [PATCH] fix bug 90623 - allow redeclaration of typedefs of same type - allow redeclaration of a typedef to itself - if the type of a typedef is a typedef, return that typedef's type for getType() - when considering declared offset of a template instance, use the templated version --- .../tests/ast2/AST2CPPSpecFailingTest.java | 71 ---------------- .../parser/tests/ast2/AST2CPPSpecTest.java | 63 +++++++++++++++ .../core/parser/tests/ast2/AST2CPPTests.java | 40 ++++++++++ .../core/dom/parser/cpp/CPPSemantics.java | 59 +++++++++----- .../core/dom/parser/cpp/CPPTypedef.java | 9 ++- .../core/dom/parser/cpp/CPPVisitor.java | 80 ++++++++++++------- 6 files changed, 201 insertions(+), 121 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java index 46a68871a93..158972cdae9 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java @@ -269,29 +269,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest { } } - /** - [--Start Example(CPP 7.1.3-2): - typedef struct s { // - } s; - typedef int I; - typedef int I; - typedef I I; - --End Example] - */ - public void test7_1_3s2() { // TODO raised bug 90623 - StringBuffer buffer = new StringBuffer(); - buffer.append("typedef struct s { //\n"); //$NON-NLS-1$ - buffer.append("} s;\n"); //$NON-NLS-1$ - buffer.append("typedef int I;\n"); //$NON-NLS-1$ - buffer.append("typedef int I;\n"); //$NON-NLS-1$ - buffer.append("typedef I I;\n"); //$NON-NLS-1$ - try { - parse(buffer.toString(), ParserLanguage.CPP, true, true); - assertTrue(false); - } catch (Exception e) { - } - } - /** [--Start Example(CPP 7.3.3-10): namespace A { @@ -891,27 +868,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest { } } - /** - [--Start Example(CPP 14.5.1.3-1): - template class X { - static T s; - }; - template T X::s = 0; - --End Example] - */ - public void test14_5_1_3s1() { // TODO no bug raised on this, can't reproduce in AST View - StringBuffer buffer = new StringBuffer(); - buffer.append("template class X {\n"); //$NON-NLS-1$ - buffer.append("static T s;\n"); //$NON-NLS-1$ - buffer.append("};\n"); //$NON-NLS-1$ - buffer.append("template T X::s = 0;\n"); //$NON-NLS-1$ - try { - parse(buffer.toString(), ParserLanguage.CPP, true, true); - assertTrue(false); - } catch (Exception e) { - } - } - /** [--Start Example(CPP 14.5.3-1): template class task; @@ -1275,33 +1231,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest { } } - /** - [--Start Example(CPP 14.7-6): - template class X { - static T s; - // ... - }; - template T X::s = 0; - X aa; - X bb; - --End Example] - */ - public void test14_7s6() { // TODO can't reproduce via ASTDOM View - StringBuffer buffer = new StringBuffer(); - buffer.append("template class X {\n"); //$NON-NLS-1$ - buffer.append("static T s;\n"); //$NON-NLS-1$ - buffer.append("// ...\n"); //$NON-NLS-1$ - buffer.append("};\n"); //$NON-NLS-1$ - buffer.append("template T X::s = 0;\n"); //$NON-NLS-1$ - buffer.append("X aa;\n"); //$NON-NLS-1$ - buffer.append("X bb;\n"); //$NON-NLS-1$ - try { - parse(buffer.toString(), ParserLanguage.CPP, true, true); - assertTrue(false); - } catch (Exception e) { - } - } - /** [--Start Example(CPP 14.7.1-5): template struct S { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java index 3a9de521b4c..a34074c07d3 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java @@ -1914,6 +1914,27 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { parse(buffer.toString(), ParserLanguage.CPP, true, true); } + /** + [--Start Example(CPP 7.1.3-2): + typedef struct s { // + } s; + typedef int I; + typedef int I; + typedef I I; + --End Example] + */ + public void test7_1_3s2() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("typedef struct s { //\n"); //$NON-NLS-1$ + buffer.append("} s;\n"); //$NON-NLS-1$ + buffer.append("typedef int I;\n"); //$NON-NLS-1$ + buffer.append("typedef int I;\n"); //$NON-NLS-1$ + buffer.append("typedef I I;\n"); //$NON-NLS-1$ + + parse(buffer.toString(), ParserLanguage.CPP, true, true); + } + + /** [--Start Example(CPP 7.1.3-3a): class complex { // @@ -8887,6 +8908,24 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { parse(buffer.toString(), ParserLanguage.CPP, false, false); } + /** + [--Start Example(CPP 14.5.1.3-1): + template class X { + static T s; + }; + template T X::s = 0; + --End Example] + */ + public void test14_5_1_3s1() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("template class X {\n"); //$NON-NLS-1$ + buffer.append("static T s;\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("template T X::s = 0;\n"); //$NON-NLS-1$ + + parse(buffer.toString(), ParserLanguage.CPP, true, true); + } + /** [--Start Example(CPP 14.5.3-2): namespace N { @@ -9680,6 +9719,30 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { parse(buffer.toString(), ParserLanguage.CPP, true, true); } + /** + [--Start Example(CPP 14.7-6): + template class X { + static T s; + // ... + }; + template T X::s = 0; + X aa; + X bb; + --End Example] + */ + public void test14_7s6() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("template class X {\n"); //$NON-NLS-1$ + buffer.append("static T s;\n"); //$NON-NLS-1$ + buffer.append("// ...\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("template T X::s = 0;\n"); //$NON-NLS-1$ + buffer.append("X aa;\n"); //$NON-NLS-1$ + buffer.append("X bb;\n"); //$NON-NLS-1$ + + parse(buffer.toString(), ParserLanguage.CPP, true, true); + } + /** [--Start Example(CPP 14.7.1-3): template class Z { 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 0d6260be676..e2e77da4291 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 @@ -3509,5 +3509,45 @@ public class AST2CPPTests extends AST2BaseTest { assertEquals(col.getName(154).toString(), "operator <"); //$NON-NLS-1$ assertEquals(col.getName(158).toString(), "operator >"); //$NON-NLS-1$ } + + public void testBug90623() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append( "typedef int I; \n"); //$NON-NLS-1$ + buffer.append( "typedef int I; \n"); //$NON-NLS-1$ + buffer.append( "typedef I I; \n"); //$NON-NLS-1$ + buffer.append( "class A { \n"); //$NON-NLS-1$ + buffer.append( " typedef char I; \n"); //$NON-NLS-1$ + buffer.append( " typedef char I; \n"); //$NON-NLS-1$ + buffer.append( " typedef I I; \n"); //$NON-NLS-1$ + buffer.append( "}; \n"); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); //$NON-NLS-1$ + CPPNameCollector col = new CPPNameCollector(); + tu.accept( col ); + + ITypedef I1 = (ITypedef) col.getName(0).resolveBinding(); + ITypedef I2 = (ITypedef) col.getName(1).resolveBinding(); + ITypedef I3 = (ITypedef) col.getName(2).resolveBinding(); + ITypedef I4 = (ITypedef) col.getName(3).resolveBinding(); + ITypedef I8 = (ITypedef) col.getName(5).resolveBinding(); + ITypedef I5 = (ITypedef) col.getName(8).resolveBinding(); + ITypedef I6 = (ITypedef) col.getName(7).resolveBinding(); + ITypedef I7 = (ITypedef) col.getName(6).resolveBinding(); + //ITypedef I8 = (ITypedef) col.getName(5).resolveBinding(); + + assertSame( I1, I2 ); + assertSame( I2, I3 ); + assertSame( I3, I4 ); + assertNotSame( I4, I5 ); + assertSame( I5, I6 ); + assertSame( I6, I7 ); + assertSame( I7, I8 ); + + assertTrue( I1.getType() instanceof IBasicType ); + assertEquals( ((IBasicType)I1.getType()).getType(), IBasicType.t_int ); + + assertTrue( I8.getType() instanceof IBasicType ); + assertEquals( ((IBasicType)I8.getType()).getType(), IBasicType.t_char ); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java index c91893fa009..15410719ae6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java @@ -91,6 +91,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; @@ -123,6 +124,7 @@ public class CPPSemantics { public ObjectSet inheritanceChain; //used to detect circular inheritance public ObjectSet associated = ObjectSet.EMPTY_SET; + public boolean checkWholeClassScope = false; public boolean ignoreUsingDirectives = false; public boolean usingDirectivesOnly = false; public boolean forceQualified = false; @@ -142,6 +144,7 @@ public class CPPSemantics { this.name = n.toCharArray(); typesOnly = typesOnly(); considerConstructors = considerConstructors(); + checkWholeClassScope = checkWholeClassScope(); } public LookupData( char [] n ){ astName = null; @@ -235,25 +238,35 @@ public class CPPSemantics { p1 = p1.getParent(); return ( p1 instanceof IASTIdExpression && p1.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME ); } - public boolean checkWholeClassScope() { + private boolean checkWholeClassScope() { if( astName == null ) return false; if( astName.getPropertyInParent() == STRING_LOOKUP_PROPERTY ) return true; - ASTNodeProperty prop = astName.getPropertyInParent(); - if( prop == ICPPASTQualifiedName.SEGMENT_NAME ) - prop = astName.getParent().getPropertyInParent(); - if( prop == IASTIdExpression.ID_NAME || - prop == IASTFieldReference.FIELD_NAME || - prop == ICASTFieldDesignator.FIELD_NAME || - prop == ICPPASTUsingDirective.QUALIFIED_NAME || - prop == ICPPASTUsingDeclaration.NAME || - prop == IASTFunctionCallExpression.FUNCTION_NAME || - prop == ICPPASTUsingDeclaration.NAME || - prop == IASTNamedTypeSpecifier.NAME ) - { - return true; + + IASTNode parent = astName.getParent(); + while( parent != null && !(parent instanceof IASTFunctionDefinition) ){ + parent = parent.getParent(); + } + if( parent instanceof IASTFunctionDefinition ){ + if( parent.getPropertyInParent() != IASTCompositeTypeSpecifier.MEMBER_DECLARATION ) + return false; + + ASTNodeProperty prop = astName.getPropertyInParent(); + if( prop == ICPPASTQualifiedName.SEGMENT_NAME ) + prop = astName.getParent().getPropertyInParent(); + if( prop == IASTIdExpression.ID_NAME || + prop == IASTFieldReference.FIELD_NAME || + prop == ICASTFieldDesignator.FIELD_NAME || + prop == ICPPASTUsingDirective.QUALIFIED_NAME || + prop == ICPPASTUsingDeclaration.NAME || + prop == IASTFunctionCallExpression.FUNCTION_NAME || + prop == IASTNamedTypeSpecifier.NAME ) + { + return true; + } } return false; } + public boolean hasResults(){ if( foundItems == null ) return false; @@ -491,6 +504,12 @@ public class CPPSemantics { parent = parent.getParent(); } + if( parent instanceof IASTDeclarator && parent.getPropertyInParent() == IASTSimpleDeclaration.DECLARATOR ){ + IASTSimpleDeclaration simple = (IASTSimpleDeclaration) parent.getParent(); + if( simple.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ) + data.forceQualified = true; + } + if( parent instanceof ICPPASTFunctionDeclarator ){ data.functionParameters = ((ICPPASTFunctionDeclarator)parent).getParameters(); } else if( parent instanceof IASTIdExpression ){ @@ -694,7 +713,7 @@ public class CPPSemantics { IBinding binding = data.prefixLookup ? null : scope.getBinding( data.astName, true ); if( binding != null && ( CPPSemantics.declaredBefore( binding, data.astName ) || - (scope instanceof ICPPClassScope && data.checkWholeClassScope()) ) ) + (scope instanceof ICPPClassScope && data.checkWholeClassScope) ) ) { mergeResults( data, binding, true ); } @@ -1024,7 +1043,7 @@ public class CPPSemantics { } int idx = -1; - boolean checkWholeClassScope = ( scope instanceof ICPPClassScope ) && data.checkWholeClassScope(); + boolean checkWholeClassScope = ( scope instanceof ICPPClassScope ) && data.checkWholeClassScope; IASTNode item = ( nodes != null ? (nodes.length > 0 ? nodes[++idx] : null ) : parent ); IASTNode [][] nodeStack = null; int [] nodeIdxStack = null; @@ -1132,7 +1151,7 @@ public class CPPSemantics { IBinding binding = temp.getBinding( data.astName, true ); if( binding != null && ( CPPSemantics.declaredBefore( binding, data.astName ) || - (scope instanceof ICPPClassScope && data.checkWholeClassScope()) ) ) + (scope instanceof ICPPClassScope && data.checkWholeClassScope) ) ) { mergeResults( data, binding, true ); found = true; @@ -1335,6 +1354,10 @@ public class CPPSemantics { if( node.getPropertyInParent() == STRING_LOOKUP_PROPERTY ) return true; ASTNode nd = null; + if( obj instanceof ICPPTemplateInstance ){ + obj = ((ICPPTemplateInstance)obj).getOriginalBinding(); + } + if( obj instanceof ICPPInternalBinding ){ ICPPInternalBinding cpp = (ICPPInternalBinding) obj; IASTNode[] n = cpp.getDeclarations(); @@ -1397,7 +1420,7 @@ public class CPPSemantics { for( int i = 0; i < items.length && items[i] != null; i++ ){ Object o = items[i]; boolean declaredBefore = declaredBefore( o, name ); - if( !data.checkWholeClassScope() && !declaredBefore ) + if( !data.checkWholeClassScope && !declaredBefore ) continue; if( o instanceof IASTName ){ temp = ((IASTName) o).resolveBinding(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTypedef.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTypedef.java index 0b9e585de9d..24068f6762b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTypedef.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTypedef.java @@ -97,8 +97,15 @@ public class CPPTypedef implements ITypedef, ITypeContainer, ICPPInternalBinding * @see org.eclipse.cdt.core.dom.ast.ITypedef#getType() */ public IType getType() { - if( type == null ) + if( type == null ){ type = CPPVisitor.createType( (IASTDeclarator) typedefName.getParent() ); + if( type instanceof ITypedef ){ + try { + type = ((ITypedef)type).getType(); + } catch ( DOMException e ) { + } + } + } return type; } 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 8e3c54d6d81..0e45f8c55b3 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 @@ -461,6 +461,7 @@ public class CPPVisitor { binding = null; } + IASTSimpleDeclaration simpleDecl = ( parent instanceof IASTSimpleDeclaration ) ? (IASTSimpleDeclaration)parent : null; if( parent instanceof ICPPASTParameterDeclaration ){ ICPPASTParameterDeclaration param = (ICPPASTParameterDeclaration) parent; parent = param.getParent(); @@ -478,6 +479,32 @@ public class CPPVisitor { } else if( parent instanceof ICPPASTTemplateDeclaration ) { return CPPTemplates.createBinding( param ); } + } else if( simpleDecl != null && simpleDecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ){ + if( binding == null ){ + binding = CPPSemantics.resolveBinding( name ); + try { + if( (binding instanceof IProblemBinding && ((IProblemBinding)binding).getID() == IProblemBinding.SEMANTIC_NAME_NOT_FOUND) || + binding.getScope() != scope ) + { + binding = null; + } + } catch ( DOMException e ){ + binding = null; + } + } + if( binding != null && binding instanceof ITypedef ){ + try { + IType t1 = ((ITypedef)binding).getType(); + IType t2 = createType( declarator ); + if( t1 != null && t2 != null && t1.equals( t2 ) ){ + ((ICPPInternalBinding)binding).addDeclaration( name ); + return binding; + } + } catch ( DOMException e1 ) { + } + return new ProblemBinding( name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, name.toCharArray() ); + } + binding = new CPPTypedef( name ); } else if( declarator instanceof ICPPASTFunctionDeclarator ){ if( binding != null && binding instanceof IFunction ){ IFunction function = (IFunction) binding; @@ -495,10 +522,8 @@ public class CPPVisitor { return function; } } - IASTSimpleDeclaration simpleDecl = ( parent instanceof IASTSimpleDeclaration ) ? (IASTSimpleDeclaration)parent : null; - if( simpleDecl != null && simpleDecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ){ - binding = new CPPTypedef( name ); - } else if( scope instanceof ICPPClassScope ){ + + if( scope instanceof ICPPClassScope ){ if( isConstructor( scope, declarator) ) binding = template ? (ICPPConstructor) new CPPConstructorTemplate( name ) : new CPPConstructor( (ICPPASTFunctionDeclarator) declarator ); @@ -510,33 +535,26 @@ public class CPPVisitor { : new CPPFunction( (ICPPASTFunctionDeclarator) declarator ); } } else if( parent instanceof IASTSimpleDeclaration ){ - - IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) parent; - if( simpleDecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ){ - binding = new CPPTypedef( name ); - } else { - IType t1 = null, t2 = null; - - if( binding != null && binding instanceof IVariable ){ - t1 = createType( declarator ); - try { - t2 = ((IVariable)binding).getType(); - } catch ( DOMException e1 ) { - } - } - if( t1 != null && t2 != null ){ - if( t1.equals( t2 ) ){ - if( binding instanceof ICPPInternalBinding ) - ((ICPPInternalBinding)binding).addDeclaration( name ); - } else { - binding = new ProblemBinding( name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, declarator.getName().toCharArray() ); - } - } else if( simpleDecl.getParent() instanceof ICPPASTCompositeTypeSpecifier ){ - binding = new CPPField( name ); - } else { - binding = new CPPVariable( name ); - } - } + IType t1 = null, t2 = null; + if( binding != null && binding instanceof IVariable ){ + t1 = createType( declarator ); + try { + t2 = ((IVariable)binding).getType(); + } catch ( DOMException e1 ) { + } + } + if( t1 != null && t2 != null ){ + if( t1.equals( t2 ) ){ + if( binding instanceof ICPPInternalBinding ) + ((ICPPInternalBinding)binding).addDeclaration( name ); + } else { + binding = new ProblemBinding( name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, declarator.getName().toCharArray() ); + } + } else if( simpleDecl.getParent() instanceof ICPPASTCompositeTypeSpecifier ){ + binding = new CPPField( name ); + } else { + binding = new CPPVariable( name ); + } } if( scope != null && binding != null ){