1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-02 22:55:26 +02:00

-work on bug 50984: fix NPEs/CCEs caused by problems with typedefs and a bug in template instantiations

-fix bug 59892: completion on typedefs
-handle ASTExpression as a context for content assist
This commit is contained in:
Andrew Niefer 2004-04-26 20:33:12 +00:00
parent 7c63d5bffc
commit 6797f7dd40
14 changed files with 128 additions and 154 deletions

View file

@ -1,66 +0,0 @@
/**********************************************************************
* Copyright (c) 2002-2004 IBM Canada and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* IBM Rational Software - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.core.parser.failedTests;
import java.io.StringWriter;
import org.eclipse.cdt.core.parser.ast.IASTCompletionNode;
import org.eclipse.cdt.core.parser.ast.IASTNode;
import org.eclipse.cdt.core.parser.ast.IASTNode.ILookupResult;
import org.eclipse.cdt.core.parser.tests.CompletionParseBaseTest;
/**
* @author johnc
*/
public class CompletionParseFailedTest extends CompletionParseBaseTest {
/**
*
*/
public CompletionParseFailedTest() {
super();
// TODO Auto-generated constructor stub
}
/**
* @param name
*/
public CompletionParseFailedTest(String name) {
super(name);
// TODO Auto-generated constructor stub
}
public void testCompletionInTypeDef() throws Exception{
StringWriter writer = new StringWriter();
writer.write( "struct A { int name; }; \n" );
writer.write( "typedef struct A * PA; \n" );
writer.write( "int main() { \n" );
writer.write( " PA a; \n" );
writer.write( " a->SP \n" );
writer.write( "} \n" );
String code = writer.toString();
int index = code.indexOf( "SP" );
IASTCompletionNode node = parse( code, index );
ILookupResult result = node.getCompletionScope().lookup( node.getCompletionPrefix(),
new IASTNode.LookupKind[]{ IASTNode.LookupKind.ALL },
node.getCompletionContext() );
//this is where the failure happens ... when the bug is fixed this line can be removed and the rest uncommented
assertEquals( result.getResultsSize(), 4 );
// assertEquals( result.getResultsSize(), 1 );
//
// Iterator iter = result.getNodes();
// IASTField name = (IASTField) iter.next();
//
// assertEquals( name.getName(), "name" );
// assertFalse( iter.hasNext() );
}
}

View file

@ -37,6 +37,7 @@ import org.eclipse.cdt.core.parser.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.parser.ast.IASTReference;
import org.eclipse.cdt.core.parser.ast.IASTScope;
import org.eclipse.cdt.core.parser.ast.IASTSimpleTypeSpecifier;
import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration;
import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration;
import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration;
import org.eclipse.cdt.core.parser.ast.IASTUsingDirective;
@ -1657,4 +1658,26 @@ public class CompleteParseASTTest extends CompleteParseBaseTest
assertAllReferences( 3, createTaskList( new Task( A, 2 ), new Task( a )));
}
public void testBug50984_ASTMethod_getOwnerClassSpecifier_ClassCastException() throws Exception
{
Writer writer = new StringWriter();
writer.write( "template < typename _OutIter > " );
writer.write( "class num_put { " );
writer.write( " typedef _OutIter iter_type; " );
writer.write( " template< typename _ValueT > " );
writer.write( " iter_type _M_convert_float( iter_type ); " );
writer.write( "}; " );
writer.write( "template < typename _OutIter > " );
writer.write( "template < typename _ValueT > " );
writer.write( "_OutIter num_put<_OutIter>::_M_convert_float( _OutIter ) { } " );
Iterator i = parse( writer.toString() ).getDeclarations();
IASTTemplateDeclaration template = (IASTTemplateDeclaration) i.next();
IASTClassSpecifier num_put = (IASTClassSpecifier) template.getOwnedDeclaration();
IASTTemplateDeclaration defn = (IASTTemplateDeclaration) i.next();
IASTMethod convert = (IASTMethod) defn.getOwnedDeclaration();
assertEquals( convert.getOwnerClassSpecifier(), num_put );
}
}

View file

@ -812,4 +812,29 @@ public class CompletionParseTest extends CompletionParseBaseTest {
}
}
public void testCompletionInTypeDef() throws Exception{
StringWriter writer = new StringWriter();
writer.write( "struct A { int name; }; \n" );
writer.write( "typedef struct A * PA; \n" );
writer.write( "int main() { \n" );
writer.write( " PA a; \n" );
writer.write( " a->SP \n" );
writer.write( "} \n" );
String code = writer.toString();
int index = code.indexOf( "SP" );
IASTCompletionNode node = parse( code, index );
ILookupResult result = node.getCompletionScope().lookup( node.getCompletionPrefix(),
new IASTNode.LookupKind[]{ IASTNode.LookupKind.ALL },
node.getCompletionContext() );
assertEquals( result.getResultsSize(), 1 );
Iterator iter = result.getNodes();
IASTField name = (IASTField) iter.next();
assertEquals( name.getName(), "name" );
assertFalse( iter.hasNext() );
}
}

View file

@ -18,7 +18,6 @@ import org.eclipse.cdt.core.model.tests.BinaryTests;
import org.eclipse.cdt.core.model.tests.ElementDeltaTests;
import org.eclipse.cdt.core.model.tests.WorkingCopyTests;
import org.eclipse.cdt.core.parser.failedTests.ASTFailedTests;
import org.eclipse.cdt.core.parser.failedTests.CompletionParseFailedTest;
import org.eclipse.cdt.core.parser.failedTests.FailedCompleteParseASTTest;
import org.eclipse.cdt.core.parser.failedTests.STLFailedTests;
import org.eclipse.cdt.core.parser.tests.ParserTestSuite;
@ -68,7 +67,6 @@ public class AutomatedIntegrationSuite extends TestSuite {
suite.addTestSuite(ASTFailedTests.class);
suite.addTestSuite(STLFailedTests.class);
suite.addTestSuite(FailedCompleteParseASTTest.class);
suite.addTestSuite(CompletionParseFailedTest.class);
return suite;
}

View file

@ -17,7 +17,7 @@ import org.eclipse.cdt.core.parser.ISourceElementCallbackDelegate;
* @author jcamelon
*
*/
public interface IASTTemplateParameter extends IASTTemplateParameterList, ISourceElementCallbackDelegate {
public interface IASTTemplateParameter extends IASTTemplateParameterList, IASTTypeSpecifier, ISourceElementCallbackDelegate {
public class ParamKind extends Enum
{

View file

@ -20,6 +20,8 @@ import org.eclipse.cdt.core.parser.ast.ASTNotImplementedException;
import org.eclipse.cdt.core.parser.ast.IASTExpression;
import org.eclipse.cdt.core.parser.ast.IASTReference;
import org.eclipse.cdt.core.parser.ast.IASTTypeId;
import org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol;
import org.eclipse.cdt.internal.core.parser.pst.TypeInfo;
/**
* @author jcamelon
@ -308,4 +310,20 @@ public class ASTExpression extends ASTNode implements IASTExpression
}
return stringRepresentation;
}
public IContainerSymbol getLookupQualificationSymbol() throws LookupError {
ExpressionResult result = getResultType();
TypeInfo type = (result != null ) ? getResultType().getResult() : null;
if( type != null ){
type = type.getFinalType();
if( type.isType( TypeInfo.t_type ) &&
type.getTypeSymbol() != null && type.getTypeSymbol() instanceof IContainerSymbol )
{
return (IContainerSymbol) type.getTypeSymbol();
}
}
return null;
}
}

View file

@ -17,9 +17,6 @@ import java.util.ListIterator;
import org.eclipse.cdt.core.parser.ParserMode;
import org.eclipse.cdt.core.parser.ast.ASTNotImplementedException;
import org.eclipse.cdt.core.parser.ast.IASTNode;
import org.eclipse.cdt.core.parser.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration;
import org.eclipse.cdt.core.parser.ast.IASTVariable;
import org.eclipse.cdt.internal.core.parser.ast.SymbolIterator;
import org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol;
import org.eclipse.cdt.internal.core.parser.pst.IExtensibleSymbol;
@ -28,7 +25,6 @@ import org.eclipse.cdt.internal.core.parser.pst.ISymbolOwner;
import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTableError;
import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTableException;
import org.eclipse.cdt.internal.core.parser.pst.TypeFilter;
import org.eclipse.cdt.internal.core.parser.pst.TypeInfo;
/**
* @author aniefer
@ -40,7 +36,7 @@ public class ASTNode implements IASTNode {
*/
public ILookupResult lookup(String prefix, LookupKind[] kind, IASTNode context) throws LookupError, ASTNotImplementedException {
if( ! ( this instanceof ISymbolOwner ) || ( context != null && !(context instanceof ISymbolOwner) ) ){
if( ! ( this instanceof ISymbolOwner ) ){
return null;
}
@ -49,7 +45,7 @@ public class ASTNode implements IASTNode {
throw new LookupError();
}
IContainerSymbol thisContainer = (IContainerSymbol) symbol;
IContainerSymbol qualification = getQualificationSymbol(context);
IContainerSymbol qualification = ( context != null ) ? ((ASTNode)context).getLookupQualificationSymbol() : null;
if( thisContainer.getSymbolTable().getParserMode() != ParserMode.COMPLETION_PARSE ){
throw new ASTNotImplementedException();
@ -126,33 +122,8 @@ public class ASTNode implements IASTNode {
* @return
* @throws LookupError
*/
protected IContainerSymbol getQualificationSymbol(IASTNode context) throws LookupError {
if( context == null )
return null;
ISymbol sym = null;
if( context instanceof IASTTypedefDeclaration ||
context instanceof IASTVariable ||
context instanceof IASTParameterDeclaration )
{
sym = ((ISymbolOwner)context).getSymbol();
TypeInfo info = null;
try{
info = sym.getTypeInfo().getFinalType();
} catch( ParserSymbolTableError e ){
throw new LookupError();
}
sym = info.getTypeSymbol();
}
else
{
sym = (IContainerSymbol) ((ISymbolOwner)context).getSymbol();
}
if( sym == null || !(sym instanceof IContainerSymbol) ){
throw new LookupError();
}
return (IContainerSymbol) sym;
public IContainerSymbol getLookupQualificationSymbol() throws LookupError {
throw new LookupError();
}
private class Result implements ILookupResult{

View file

@ -12,8 +12,11 @@ package org.eclipse.cdt.internal.core.parser.ast.complete;
import org.eclipse.cdt.core.parser.ast.IASTDeclaration;
import org.eclipse.cdt.core.parser.ast.IASTScope;
import org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol;
import org.eclipse.cdt.internal.core.parser.pst.ISymbol;
import org.eclipse.cdt.internal.core.parser.pst.ISymbolOwner;
import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTableError;
import org.eclipse.cdt.internal.core.parser.pst.TypeInfo;
/**
* @author jcamelon
@ -37,4 +40,20 @@ public abstract class ASTSymbol extends ASTSymbolOwner implements ISymbolOwner,
return null;
}
public IContainerSymbol getLookupQualificationSymbol() throws LookupError {
ISymbol sym = getSymbol();
TypeInfo info = null;
try{
info = sym.getTypeInfo().getFinalType();
} catch( ParserSymbolTableError e ){
throw new LookupError();
}
if( info.isType( TypeInfo.t_type ) && info.getTypeSymbol() != null && info.getTypeSymbol() instanceof IContainerSymbol )
return (IContainerSymbol) info.getTypeSymbol();
else if( sym instanceof IContainerSymbol )
return (IContainerSymbol) sym;
return null;
}
}

View file

@ -2879,14 +2879,22 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
int startingLine, int nameOffset, int nameEndOffset, int nameLine) throws ASTSemanticException
{
IContainerSymbol containerSymbol = scopeToSymbol(scope);
ISymbol newSymbol = pst.newSymbol( name, TypeInfo.t_type);
newSymbol.getTypeInfo().setBit( true,TypeInfo.isTypedef );
ISymbol typeSymbol = cloneSimpleTypeSymbol( EMPTY_STRING, mapping, new ArrayList() );
ISymbol typeSymbol = cloneSimpleTypeSymbol( name, mapping, new ArrayList() );
if( typeSymbol == null )
handleProblem( scope, IProblem.SEMANTICS_RELATED, name, nameOffset, nameEndOffset, nameLine );
setPointerOperators( typeSymbol, mapping.getPointerOperators(), mapping.getArrayModifiers() );
newSymbol.setTypeSymbol( typeSymbol );
if( typeSymbol.getType() != TypeInfo.t_type ){
ISymbol newSymbol = pst.newSymbol( name, TypeInfo.t_type);
newSymbol.getTypeInfo().setBit( true,TypeInfo.isTypedef );
newSymbol.setTypeSymbol( typeSymbol );
typeSymbol = newSymbol;
} else {
typeSymbol.getTypeInfo().setBit( true,TypeInfo.isTypedef );
}
List references = new ArrayList();
if( mapping.getTypeSpecifier() instanceof ASTSimpleTypeSpecifier )
{
@ -2895,14 +2903,14 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
try
{
containerSymbol.addSymbol( newSymbol );
containerSymbol.addSymbol( typeSymbol );
}
catch (ParserSymbolTableException e)
{
handleProblem(e.createProblemID(), name );
}
ASTTypedef d = new ASTTypedef( newSymbol, mapping, startingOffset, startingLine, nameOffset, nameEndOffset, nameLine, references );
attachSymbolExtension(newSymbol, d, true );
ASTTypedef d = new ASTTypedef( typeSymbol, mapping, startingOffset, startingLine, nameOffset, nameEndOffset, nameLine, references );
attachSymbolExtension(typeSymbol, d, true );
return d;
}
/* (non-Javadoc)

View file

@ -14,6 +14,8 @@ import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.core.parser.ISourceElementRequestor;
import org.eclipse.cdt.core.parser.ast.ASTNotImplementedException;
import org.eclipse.cdt.core.parser.ast.IASTNode;
import org.eclipse.cdt.core.parser.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.parser.ast.IASTTemplateParameter;
@ -93,5 +95,12 @@ public class ASTTemplateParameter implements IASTTemplateParameter
*/
public void exitScope(ISourceElementRequestor requestor) {
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.parser.ast.IASTNode#lookup(java.lang.String, org.eclipse.cdt.core.parser.ast.IASTNode.LookupKind[], org.eclipse.cdt.core.parser.ast.IASTNode)
*/
public ILookupResult lookup(String prefix, LookupKind[] kind, IASTNode context) throws LookupError, ASTNotImplementedException {
// TODO Auto-generated method stub
return null;
}
}

View file

@ -139,7 +139,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol {
if( newContainer.getContainedSymbols().containsKey( newSymbol.getName() ) ){
Object obj = newContainer.getContainedSymbols().get( newSymbol.getName() );
if( obj instanceof List ){
((List) obj).add( obj );
((List) obj).add( newSymbol );
} else {
List list = new LinkedList();
list.add( obj );

View file

@ -95,9 +95,6 @@ public class ParserSymbolTable {
return new TemplateFactory( this );
}
// public ISpecializedSymbol newSpecializedSymbol( String name, TypeInfo.eType type ){
// return new Declaration( this, name, type );
// }
/**
* Lookup the name from LookupData starting in the inDeclaration
* @param data
@ -107,10 +104,6 @@ public class ParserSymbolTable {
*/
static protected void lookup( LookupData data, IContainerSymbol inSymbol ) throws ParserSymbolTableException
{
// if( data.type != TypeInfo.t_any && data.type.compareTo(TypeInfo.t_class) < 0 && data.upperType.compareTo(TypeInfo.t_union) > 0 ){
// throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
// }
//handle namespace aliases
if( inSymbol.isType( TypeInfo.t_namespace ) ){
ISymbol symbol = inSymbol.getTypeSymbol();
@ -953,27 +946,6 @@ public class ParserSymbolTable {
resolvedSymbol = resolveFunction( data, functionList );
}
}
if( resolvedSymbol != null && resolvedSymbol.getTypeInfo().checkBit( TypeInfo.isTypedef ) ){
ISymbol symbol = resolvedSymbol.getTypeSymbol();
if( symbol == null )
return resolvedSymbol;
TypeInfo info = ParserSymbolTable.getFlatTypeInfo( symbol.getTypeInfo() );
symbol = info.getTypeSymbol();
ISymbol newSymbol = null;
if( symbol != null ){
newSymbol = (ISymbol) symbol.clone();
newSymbol.setName( resolvedSymbol.getName() );
} else {
newSymbol = resolvedSymbol.getSymbolTable().newSymbol( resolvedSymbol.getName() );
newSymbol.setTypeInfo( info );
}
newSymbol.setASTExtension( resolvedSymbol.getASTExtension() );
newSymbol.setContainingSymbol( resolvedSymbol.getContainingSymbol() );
resolvedSymbol = newSymbol;
}
return resolvedSymbol;
}
@ -1978,7 +1950,6 @@ public class ParserSymbolTable {
* The top level TypeInfo represents modifications to the object and the
* remaining TypeInfo's represent the object.
*/
// TODO move this to ITypeInfo ?
static protected TypeInfo getFlatTypeInfo( TypeInfo topInfo ){
TypeInfo returnInfo = topInfo;
TypeInfo info = null;
@ -2270,7 +2241,6 @@ public class ParserSymbolTable {
}
if( ! (qualifyingSymbol instanceof IDerivableContainerSymbol) ){
// throw new ParserSymbolTableError( ParserSymbolTableError.r_InternalError ); //TODO - Andrew, why is this an error?
return ASTAccessVisibility.PUBLIC;
}

View file

@ -61,8 +61,6 @@ public final class TemplateEngine {
TypeInfo newInfo = new TypeInfo( info );
newInfo.setTypeSymbol( info.getTypeSymbol().instantiate( template, argMap ) );
return newInfo;
} else if( info.checkBit( TypeInfo.isTypedef ) && info.getTypeSymbol() != null ){
return instantiateTypeInfo( info.getTypeSymbol().getTypeInfo(), template, argMap );
}
return info;
}
@ -443,7 +441,7 @@ public final class TemplateEngine {
if( p.isType( TypeInfo.t_type ) ){
symbol = p.getTypeSymbol();
ISymbol aSymbol = a.getTypeSymbol();
if( symbol == null || ( a.isType( TypeInfo.t_type) && aSymbol == null ) )
if( symbol == null || ( a.isType( TypeInfo.t_type) && aSymbol == null ) || a.isType( TypeInfo.t_undef ))
throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
if( symbol instanceof IDeferredTemplateInstance || symbol.isTemplateInstance() ){
return deduceFromTemplateTemplateArguments(map, symbol, aSymbol);

View file

@ -304,17 +304,18 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb
}
}
if( found != null && found.getTypeInfo().isForwardDeclaration() && found.getTypeSymbol() == symbol ){
if( found != null ){
//in defining the explicit specialization for a member function, the factory would have set
//the specialization as the definition of the original declaration, which it is not
found.setTypeSymbol( null );
}
//TODO, once we can instantiate members as we need them instead of at the same time as the class
//then found should stay as the instance, for now though, we need the original (not 100% correct
//but the best we can do for now)
while( found.isTemplateInstance() ){
found = found.getInstantiatedSymbol();
if( found.getTypeInfo().isForwardDeclaration() && found.getTypeSymbol() == symbol )
found.setTypeSymbol( null );
//TODO, once we can instantiate members as we need them instead of at the same time as the class
//then found should stay as the instance, for now though, we need the original (not 100% correct
//but the best we can do for now)
while( found.isTemplateInstance() ){
found = found.getInstantiatedSymbol();
}
}
if( found != null ){