1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

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
This commit is contained in:
Andrew Niefer 2005-04-08 22:35:30 +00:00
parent 1c3efe3b16
commit 94d86b038e
6 changed files with 201 additions and 121 deletions

View file

@ -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): [--Start Example(CPP 7.3.3-10):
namespace A { namespace A {
@ -891,27 +868,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
} }
} }
/**
[--Start Example(CPP 14.5.1.3-1):
template<class T> class X {
static T s;
};
template<class T> T X<T>::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 T> class X {\n"); //$NON-NLS-1$
buffer.append("static T s;\n"); //$NON-NLS-1$
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("template<class T> T X<T>::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): [--Start Example(CPP 14.5.3-1):
template<class T> class task; template<class T> class task;
@ -1275,33 +1231,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
} }
} }
/**
[--Start Example(CPP 14.7-6):
template<class T> class X {
static T s;
// ...
};
template<class T> T X<T>::s = 0;
X<int> aa;
X<char*> bb;
--End Example]
*/
public void test14_7s6() { // TODO can't reproduce via ASTDOM View
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> 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<class T> T X<T>::s = 0;\n"); //$NON-NLS-1$
buffer.append("X<int> aa;\n"); //$NON-NLS-1$
buffer.append("X<char*> 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): [--Start Example(CPP 14.7.1-5):
template <class T> struct S { template <class T> struct S {

View file

@ -1914,6 +1914,27 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(buffer.toString(), ParserLanguage.CPP, true, true); 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): [--Start Example(CPP 7.1.3-3a):
class complex { // class complex { //
@ -8887,6 +8908,24 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(buffer.toString(), ParserLanguage.CPP, false, false); parse(buffer.toString(), ParserLanguage.CPP, false, false);
} }
/**
[--Start Example(CPP 14.5.1.3-1):
template<class T> class X {
static T s;
};
template<class T> T X<T>::s = 0;
--End Example]
*/
public void test14_5_1_3s1() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> class X {\n"); //$NON-NLS-1$
buffer.append("static T s;\n"); //$NON-NLS-1$
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("template<class T> T X<T>::s = 0;\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, true);
}
/** /**
[--Start Example(CPP 14.5.3-2): [--Start Example(CPP 14.5.3-2):
namespace N { namespace N {
@ -9680,6 +9719,30 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(buffer.toString(), ParserLanguage.CPP, true, true); parse(buffer.toString(), ParserLanguage.CPP, true, true);
} }
/**
[--Start Example(CPP 14.7-6):
template<class T> class X {
static T s;
// ...
};
template<class T> T X<T>::s = 0;
X<int> aa;
X<char*> bb;
--End Example]
*/
public void test14_7s6() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> 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<class T> T X<T>::s = 0;\n"); //$NON-NLS-1$
buffer.append("X<int> aa;\n"); //$NON-NLS-1$
buffer.append("X<char*> bb;\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, true);
}
/** /**
[--Start Example(CPP 14.7.1-3): [--Start Example(CPP 14.7.1-3):
template<class T> class Z { template<class T> class Z {

View file

@ -3509,5 +3509,45 @@ public class AST2CPPTests extends AST2BaseTest {
assertEquals(col.getName(154).toString(), "operator <"); //$NON-NLS-1$ assertEquals(col.getName(154).toString(), "operator <"); //$NON-NLS-1$
assertEquals(col.getName(158).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 );
}
} }

View file

@ -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.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; 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.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.ICPPUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; 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 inheritanceChain; //used to detect circular inheritance
public ObjectSet associated = ObjectSet.EMPTY_SET; public ObjectSet associated = ObjectSet.EMPTY_SET;
public boolean checkWholeClassScope = false;
public boolean ignoreUsingDirectives = false; public boolean ignoreUsingDirectives = false;
public boolean usingDirectivesOnly = false; public boolean usingDirectivesOnly = false;
public boolean forceQualified = false; public boolean forceQualified = false;
@ -142,6 +144,7 @@ public class CPPSemantics {
this.name = n.toCharArray(); this.name = n.toCharArray();
typesOnly = typesOnly(); typesOnly = typesOnly();
considerConstructors = considerConstructors(); considerConstructors = considerConstructors();
checkWholeClassScope = checkWholeClassScope();
} }
public LookupData( char [] n ){ public LookupData( char [] n ){
astName = null; astName = null;
@ -235,25 +238,35 @@ public class CPPSemantics {
p1 = p1.getParent(); p1 = p1.getParent();
return ( p1 instanceof IASTIdExpression && p1.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME ); return ( p1 instanceof IASTIdExpression && p1.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME );
} }
public boolean checkWholeClassScope() { private boolean checkWholeClassScope() {
if( astName == null ) return false; if( astName == null ) return false;
if( astName.getPropertyInParent() == STRING_LOOKUP_PROPERTY ) return true; if( astName.getPropertyInParent() == STRING_LOOKUP_PROPERTY ) return true;
ASTNodeProperty prop = astName.getPropertyInParent();
if( prop == ICPPASTQualifiedName.SEGMENT_NAME ) IASTNode parent = astName.getParent();
prop = astName.getParent().getPropertyInParent(); while( parent != null && !(parent instanceof IASTFunctionDefinition) ){
if( prop == IASTIdExpression.ID_NAME || parent = parent.getParent();
prop == IASTFieldReference.FIELD_NAME || }
prop == ICASTFieldDesignator.FIELD_NAME || if( parent instanceof IASTFunctionDefinition ){
prop == ICPPASTUsingDirective.QUALIFIED_NAME || if( parent.getPropertyInParent() != IASTCompositeTypeSpecifier.MEMBER_DECLARATION )
prop == ICPPASTUsingDeclaration.NAME || return false;
prop == IASTFunctionCallExpression.FUNCTION_NAME ||
prop == ICPPASTUsingDeclaration.NAME || ASTNodeProperty prop = astName.getPropertyInParent();
prop == IASTNamedTypeSpecifier.NAME ) if( prop == ICPPASTQualifiedName.SEGMENT_NAME )
{ prop = astName.getParent().getPropertyInParent();
return true; 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; return false;
} }
public boolean hasResults(){ public boolean hasResults(){
if( foundItems == null ) if( foundItems == null )
return false; return false;
@ -491,6 +504,12 @@ public class CPPSemantics {
parent = parent.getParent(); 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 ){ if( parent instanceof ICPPASTFunctionDeclarator ){
data.functionParameters = ((ICPPASTFunctionDeclarator)parent).getParameters(); data.functionParameters = ((ICPPASTFunctionDeclarator)parent).getParameters();
} else if( parent instanceof IASTIdExpression ){ } else if( parent instanceof IASTIdExpression ){
@ -694,7 +713,7 @@ public class CPPSemantics {
IBinding binding = data.prefixLookup ? null : scope.getBinding( data.astName, true ); IBinding binding = data.prefixLookup ? null : scope.getBinding( data.astName, true );
if( binding != null && if( binding != null &&
( CPPSemantics.declaredBefore( binding, data.astName ) || ( CPPSemantics.declaredBefore( binding, data.astName ) ||
(scope instanceof ICPPClassScope && data.checkWholeClassScope()) ) ) (scope instanceof ICPPClassScope && data.checkWholeClassScope) ) )
{ {
mergeResults( data, binding, true ); mergeResults( data, binding, true );
} }
@ -1024,7 +1043,7 @@ public class CPPSemantics {
} }
int idx = -1; 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 item = ( nodes != null ? (nodes.length > 0 ? nodes[++idx] : null ) : parent );
IASTNode [][] nodeStack = null; IASTNode [][] nodeStack = null;
int [] nodeIdxStack = null; int [] nodeIdxStack = null;
@ -1132,7 +1151,7 @@ public class CPPSemantics {
IBinding binding = temp.getBinding( data.astName, true ); IBinding binding = temp.getBinding( data.astName, true );
if( binding != null && if( binding != null &&
( CPPSemantics.declaredBefore( binding, data.astName ) || ( CPPSemantics.declaredBefore( binding, data.astName ) ||
(scope instanceof ICPPClassScope && data.checkWholeClassScope()) ) ) (scope instanceof ICPPClassScope && data.checkWholeClassScope) ) )
{ {
mergeResults( data, binding, true ); mergeResults( data, binding, true );
found = true; found = true;
@ -1335,6 +1354,10 @@ public class CPPSemantics {
if( node.getPropertyInParent() == STRING_LOOKUP_PROPERTY ) return true; if( node.getPropertyInParent() == STRING_LOOKUP_PROPERTY ) return true;
ASTNode nd = null; ASTNode nd = null;
if( obj instanceof ICPPTemplateInstance ){
obj = ((ICPPTemplateInstance)obj).getOriginalBinding();
}
if( obj instanceof ICPPInternalBinding ){ if( obj instanceof ICPPInternalBinding ){
ICPPInternalBinding cpp = (ICPPInternalBinding) obj; ICPPInternalBinding cpp = (ICPPInternalBinding) obj;
IASTNode[] n = cpp.getDeclarations(); IASTNode[] n = cpp.getDeclarations();
@ -1397,7 +1420,7 @@ public class CPPSemantics {
for( int i = 0; i < items.length && items[i] != null; i++ ){ for( int i = 0; i < items.length && items[i] != null; i++ ){
Object o = items[i]; Object o = items[i];
boolean declaredBefore = declaredBefore( o, name ); boolean declaredBefore = declaredBefore( o, name );
if( !data.checkWholeClassScope() && !declaredBefore ) if( !data.checkWholeClassScope && !declaredBefore )
continue; continue;
if( o instanceof IASTName ){ if( o instanceof IASTName ){
temp = ((IASTName) o).resolveBinding(); temp = ((IASTName) o).resolveBinding();

View file

@ -97,8 +97,15 @@ public class CPPTypedef implements ITypedef, ITypeContainer, ICPPInternalBinding
* @see org.eclipse.cdt.core.dom.ast.ITypedef#getType() * @see org.eclipse.cdt.core.dom.ast.ITypedef#getType()
*/ */
public IType getType() { public IType getType() {
if( type == null ) if( type == null ){
type = CPPVisitor.createType( (IASTDeclarator) typedefName.getParent() ); type = CPPVisitor.createType( (IASTDeclarator) typedefName.getParent() );
if( type instanceof ITypedef ){
try {
type = ((ITypedef)type).getType();
} catch ( DOMException e ) {
}
}
}
return type; return type;
} }

View file

@ -461,6 +461,7 @@ public class CPPVisitor {
binding = null; binding = null;
} }
IASTSimpleDeclaration simpleDecl = ( parent instanceof IASTSimpleDeclaration ) ? (IASTSimpleDeclaration)parent : null;
if( parent instanceof ICPPASTParameterDeclaration ){ if( parent instanceof ICPPASTParameterDeclaration ){
ICPPASTParameterDeclaration param = (ICPPASTParameterDeclaration) parent; ICPPASTParameterDeclaration param = (ICPPASTParameterDeclaration) parent;
parent = param.getParent(); parent = param.getParent();
@ -478,6 +479,32 @@ public class CPPVisitor {
} else if( parent instanceof ICPPASTTemplateDeclaration ) { } else if( parent instanceof ICPPASTTemplateDeclaration ) {
return CPPTemplates.createBinding( param ); 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 ){ } else if( declarator instanceof ICPPASTFunctionDeclarator ){
if( binding != null && binding instanceof IFunction ){ if( binding != null && binding instanceof IFunction ){
IFunction function = (IFunction) binding; IFunction function = (IFunction) binding;
@ -495,10 +522,8 @@ public class CPPVisitor {
return function; return function;
} }
} }
IASTSimpleDeclaration simpleDecl = ( parent instanceof IASTSimpleDeclaration ) ? (IASTSimpleDeclaration)parent : null;
if( simpleDecl != null && simpleDecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ){ if( scope instanceof ICPPClassScope ){
binding = new CPPTypedef( name );
} else if( scope instanceof ICPPClassScope ){
if( isConstructor( scope, declarator) ) if( isConstructor( scope, declarator) )
binding = template ? (ICPPConstructor) new CPPConstructorTemplate( name ) binding = template ? (ICPPConstructor) new CPPConstructorTemplate( name )
: new CPPConstructor( (ICPPASTFunctionDeclarator) declarator ); : new CPPConstructor( (ICPPASTFunctionDeclarator) declarator );
@ -510,33 +535,26 @@ public class CPPVisitor {
: new CPPFunction( (ICPPASTFunctionDeclarator) declarator ); : new CPPFunction( (ICPPASTFunctionDeclarator) declarator );
} }
} else if( parent instanceof IASTSimpleDeclaration ){ } else if( parent instanceof IASTSimpleDeclaration ){
IType t1 = null, t2 = null;
IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) parent; if( binding != null && binding instanceof IVariable ){
if( simpleDecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ){ t1 = createType( declarator );
binding = new CPPTypedef( name ); try {
} else { t2 = ((IVariable)binding).getType();
IType t1 = null, t2 = null; } catch ( DOMException e1 ) {
}
if( binding != null && binding instanceof IVariable ){ }
t1 = createType( declarator ); if( t1 != null && t2 != null ){
try { if( t1.equals( t2 ) ){
t2 = ((IVariable)binding).getType(); if( binding instanceof ICPPInternalBinding )
} catch ( DOMException e1 ) { ((ICPPInternalBinding)binding).addDeclaration( name );
} } else {
} binding = new ProblemBinding( name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, declarator.getName().toCharArray() );
if( t1 != null && t2 != null ){ }
if( t1.equals( t2 ) ){ } else if( simpleDecl.getParent() instanceof ICPPASTCompositeTypeSpecifier ){
if( binding instanceof ICPPInternalBinding ) binding = new CPPField( name );
((ICPPInternalBinding)binding).addDeclaration( name ); } else {
} else { binding = new CPPVariable( name );
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 ){ if( scope != null && binding != null ){