mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
- consider template parameter default values
- partially fixes 76951, fixes 90670
This commit is contained in:
parent
8230e97539
commit
5b282cb2f4
9 changed files with 174 additions and 80 deletions
|
@ -661,23 +661,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.1-13):
|
||||
template<class T, T* p, class U = T> class X { };
|
||||
template<class T> void f(T* p = new T);
|
||||
--End Example]
|
||||
*/
|
||||
public void test14_1s13() { // TODO raised bug 60670
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("template<class T, T* p, class U = T> class X { };\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class T> void f(T* p = new T);\n"); //$NON-NLS-1$
|
||||
try {
|
||||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||
assertTrue(false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.3-2):
|
||||
template<class T> void f();
|
||||
|
@ -931,23 +914,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.6.1-3a):
|
||||
template<class T, T* p, class U = T> class X { };
|
||||
template<class T> void f(T* p = new T);
|
||||
--End Example]
|
||||
*/
|
||||
public void test14_6_1s3a() { // TODO already have bug on this one
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("template<class T, T* p, class U = T> class X { };\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class T> void f(T* p = new T);\n"); //$NON-NLS-1$
|
||||
try {
|
||||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||
assertTrue(false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.6.1-6):
|
||||
namespace N {
|
||||
|
@ -1005,43 +971,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
|
|||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.7-3):
|
||||
template<class T = int> struct A {
|
||||
static int x;
|
||||
};
|
||||
template<class U> void g(U) { }
|
||||
template<> struct A<double> { }; // specialize for T == double
|
||||
template<> struct A<> { }; // specialize for T == int
|
||||
template<> void g(char) { } // specialize for U == char
|
||||
// U is deduced from the parameter type
|
||||
template<> void g<int>(int) { } // specialize for U == int
|
||||
template<> int A<char>::x = 0; // specialize for T == char
|
||||
template<class T = int> struct B {
|
||||
static int x;
|
||||
};
|
||||
template<> int B<>::x = 1; // specialize for T == int
|
||||
--End Example]
|
||||
*/
|
||||
public void test14_7s3() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("template<class T = int> struct A {\n"); //$NON-NLS-1$
|
||||
buffer.append("static int x;\n"); //$NON-NLS-1$
|
||||
buffer.append("};\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class U> void g(U) { }\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> struct A<double> { }; // specialize for T == double\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> struct A<> { }; // specialize for T == int\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> void g(char) { } // specialize for U == char\n"); //$NON-NLS-1$
|
||||
buffer.append("// U is deduced from the parameter type\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> void g<int>(int) { } // specialize for U == int\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> int A<char>::x = 0; // specialize for T == char\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class T = int> struct B {\n"); //$NON-NLS-1$
|
||||
buffer.append("static int x;\n"); //$NON-NLS-1$
|
||||
buffer.append("};\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> int B<>::x = 1; // specialize for T == int\n"); //$NON-NLS-1$
|
||||
parse(buffer.toString(), ParserLanguage.CPP, true, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.7.1-5):
|
||||
|
|
|
@ -8480,6 +8480,20 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
|
|||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.1-13):
|
||||
template<class T, T* p, class U = T> class X { };
|
||||
template<class T> void f(T* p = new T);
|
||||
--End Example]
|
||||
*/
|
||||
public void test14_1s13() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("template<class T, T* p, class U = T> class X { };\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class T> void f(T* p = new T);\n"); //$NON-NLS-1$
|
||||
|
||||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.1-15):
|
||||
template<int i = (3 > 4) > // OK
|
||||
|
@ -9597,7 +9611,20 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
|
|||
parse(buffer.toString(), ParserLanguage.CPP, false, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.6.1-3a):
|
||||
template<class T, T* p, class U = T> class X { };
|
||||
template<class T> void f(T* p = new T);
|
||||
--End Example]
|
||||
*/
|
||||
public void test14_6_1s3a() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("template<class T, T* p, class U = T> class X { };\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class T> void f(T* p = new T);\n"); //$NON-NLS-1$
|
||||
|
||||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.6.1-1):
|
||||
template<class T> class X {
|
||||
|
@ -9966,6 +9993,44 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
|
|||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.7-3):
|
||||
template<class T = int> struct A {
|
||||
static int x;
|
||||
};
|
||||
template<class U> void g(U) { }
|
||||
template<> struct A<double> { }; // specialize for T == double
|
||||
template<> struct A<> { }; // specialize for T == int
|
||||
template<> void g(char) { } // specialize for U == char
|
||||
// U is deduced from the parameter type
|
||||
template<> void g<int>(int) { } // specialize for U == int
|
||||
template<> int A<char>::x = 0; // specialize for T == char
|
||||
template<class T = int> struct B {
|
||||
static int x;
|
||||
};
|
||||
template<> int B<>::x = 1; // specialize for T == int
|
||||
--End Example]
|
||||
*/
|
||||
public void test14_7s3() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("template<class T = int> struct A {\n"); //$NON-NLS-1$
|
||||
buffer.append("static int x;\n"); //$NON-NLS-1$
|
||||
buffer.append("};\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class U> void g(U) { }\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> struct A<double> { }; // specialize for T == double\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> struct A<> { }; // specialize for T == int\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> void g(char) { } // specialize for U == char\n"); //$NON-NLS-1$
|
||||
buffer.append("// U is deduced from the parameter type\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> void g<int>(int) { } // specialize for U == int\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> int A<char>::x = 0; // specialize for T == char\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class T = int> struct B {\n"); //$NON-NLS-1$
|
||||
buffer.append("static int x;\n"); //$NON-NLS-1$
|
||||
buffer.append("};\n"); //$NON-NLS-1$
|
||||
buffer.append("template<> int B<>::x = 1; // specialize for T == int\n"); //$NON-NLS-1$
|
||||
|
||||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.7.1-10):
|
||||
namespace N {
|
||||
|
|
|
@ -778,4 +778,64 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
assertSame( ((ICPPTemplateInstance)f2).getOriginalBinding(), f1 );
|
||||
assertSame( g1, g2 );
|
||||
}
|
||||
|
||||
public void testBug76951_1() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("template <class T, class U = T > U f( T ); \n"); //$NON-NLS-1$
|
||||
buffer.append("void g() { \n"); //$NON-NLS-1$
|
||||
buffer.append(" f( 1 ); \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
|
||||
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
|
||||
CPPNameCollector col = new CPPNameCollector();
|
||||
tu.accept( col );
|
||||
|
||||
ICPPTemplateParameter T = (ICPPTemplateParameter) col.getName(0).resolveBinding();
|
||||
ICPPTemplateParameter T2 = (ICPPTemplateParameter) col.getName(2).resolveBinding();
|
||||
assertSame( T, T2 );
|
||||
|
||||
ICPPFunctionTemplate f1 = (ICPPFunctionTemplate) col.getName(4).resolveBinding();
|
||||
ICPPFunction f2 = (ICPPFunction) col.getName(8).resolveBinding();
|
||||
|
||||
assertTrue( f2 instanceof ICPPTemplateInstance );
|
||||
assertSame( ((ICPPTemplateInstance)f2).getOriginalBinding(), f1 );
|
||||
|
||||
IFunctionType ft = f2.getType();
|
||||
assertTrue( ft.getReturnType() instanceof IBasicType );
|
||||
assertEquals( ((IBasicType)ft.getReturnType()).getType(), IBasicType.t_int );
|
||||
}
|
||||
public void testBug76951_2() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("template <class T, class U = T > class A { \n"); //$NON-NLS-1$
|
||||
buffer.append(" U u; \n"); //$NON-NLS-1$
|
||||
buffer.append("}; \n"); //$NON-NLS-1$
|
||||
buffer.append("void f() { \n"); //$NON-NLS-1$
|
||||
buffer.append(" A<int> a; \n"); //$NON-NLS-1$
|
||||
buffer.append(" a.u; \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
|
||||
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
|
||||
CPPNameCollector col = new CPPNameCollector();
|
||||
tu.accept( col );
|
||||
|
||||
ICPPTemplateParameter T = (ICPPTemplateParameter) col.getName(0).resolveBinding();
|
||||
ICPPTemplateTypeParameter U = (ICPPTemplateTypeParameter) col.getName(1).resolveBinding();
|
||||
assertSame( U.getDefault(), T );
|
||||
|
||||
ICPPClassTemplate A = (ICPPClassTemplate) col.getName(3).resolveBinding();
|
||||
ICPPField u1 = (ICPPField) col.getName(5).resolveBinding();
|
||||
assertSame( u1.getType(), U );
|
||||
|
||||
ICPPClassType A1 = (ICPPClassType) col.getName(7).resolveBinding();
|
||||
assertTrue( A1 instanceof ICPPTemplateInstance );
|
||||
assertSame( ((ICPPTemplateInstance)A1).getOriginalBinding(), A );
|
||||
|
||||
ICPPField u2 = (ICPPField) col.getName(11).resolveBinding();
|
||||
assertTrue( u2 instanceof ICPPTemplateInstance );
|
||||
assertSame( ((ICPPTemplateInstance)u2).getOriginalBinding(), u1 );
|
||||
|
||||
IType type = u2.getType();
|
||||
assertTrue( type instanceof IBasicType );
|
||||
assertEquals( ((IBasicType)type).getType(), IBasicType.t_int );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,8 +77,9 @@ public class CPPASTSimpleTypeTemplateParameter extends CPPASTNode implements
|
|||
}
|
||||
}
|
||||
|
||||
if( typeId != null ) if( !typeId.accept( action ) ) return false;
|
||||
if( name != null ) if( !name.accept( action ) ) return false;
|
||||
if( typeId != null ) if( !typeId.accept( action ) ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -199,6 +199,8 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements
|
|||
* @see org.eclipse.cdt.core.dom.ast.ICompositeType#getCompositeScope()
|
||||
*/
|
||||
public IScope getCompositeScope() {
|
||||
if( definition == null )
|
||||
checkForDefinition();
|
||||
if( definition != null ){
|
||||
ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) definition.getParent();
|
||||
return compSpec.getScope();
|
||||
|
|
|
@ -138,7 +138,7 @@ public abstract class CPPTemplateDefinition implements ICPPTemplateDefinition, I
|
|||
IType[] actualArgs = new IType[ numParams ];
|
||||
|
||||
for( int i = 0; i < numParams; i++ ){
|
||||
|
||||
arg = null;
|
||||
param = parameters[i];
|
||||
|
||||
if( i < numArgs ){
|
||||
|
@ -164,7 +164,9 @@ public abstract class CPPTemplateDefinition implements ICPPTemplateDefinition, I
|
|||
if( map.containsKey( defaultType ) ){
|
||||
arg = (IType) map.get( defaultType );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
arg = defaultType;
|
||||
}
|
||||
} else {
|
||||
//TODO problem
|
||||
return null;
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
*/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
|
||||
|
||||
/**
|
||||
|
@ -35,8 +37,15 @@ public class CPPTemplateTypeParameter extends CPPTemplateParameter implements
|
|||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter#getDefault()
|
||||
*/
|
||||
public IType getDefault() throws DOMException {
|
||||
// TODO Auto-generated method stub
|
||||
public IType getDefault() {
|
||||
IASTNode [] nds = getDeclarations();
|
||||
if( nds == null || nds.length == 0 )
|
||||
return null;
|
||||
IASTName name = (IASTName) nds[0];
|
||||
ICPPASTSimpleTypeTemplateParameter simple = (ICPPASTSimpleTypeTemplateParameter) name.getParent();
|
||||
IASTTypeId typeId = simple.getDefaultType();
|
||||
if( typeId != null )
|
||||
return CPPVisitor.createType( typeId );
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -703,9 +703,31 @@ public class CPPTemplates {
|
|||
instanceArgs = (IType[]) ArrayUtil.append( IType.class, instanceArgs, arg );
|
||||
else
|
||||
continue outer;
|
||||
else if( arg == null && mapped == null )
|
||||
continue outer;
|
||||
else
|
||||
else if( arg == null && mapped == null ) {
|
||||
IType def = null;
|
||||
try {
|
||||
if( templateParams[i] instanceof ICPPTemplateTypeParameter ){
|
||||
def = ((ICPPTemplateTypeParameter)templateParams[i]).getDefault();
|
||||
} else if( templateParams[i] instanceof ICPPTemplateTemplateParameter ){
|
||||
def = ((ICPPTemplateTemplateParameter)templateParams[i]).getDefault();
|
||||
} else if( templateParams[i] instanceof ICPPTemplateNonTypeParameter ){
|
||||
def = CPPVisitor.getExpressionType( ((ICPPTemplateNonTypeParameter)templateParams[i]).getDefault() );
|
||||
}
|
||||
} catch ( DOMException e ) {
|
||||
continue outer;
|
||||
}
|
||||
if( def != null ){
|
||||
if( def instanceof ICPPTemplateParameter ){
|
||||
for ( int j = 0; j < i; j++ ) {
|
||||
if( templateParams[j] == def ) {
|
||||
def = instanceArgs[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
instanceArgs = (IType[]) ArrayUtil.append( IType.class, instanceArgs, def );
|
||||
} else
|
||||
continue outer;
|
||||
} else
|
||||
instanceArgs = (IType[]) ArrayUtil.append( IType.class, instanceArgs, (arg != null) ? arg : mapped );
|
||||
}
|
||||
instanceArgs = (IType[]) ArrayUtil.trim( IType.class, instanceArgs );
|
||||
|
|
|
@ -638,6 +638,8 @@ public class CPPVisitor {
|
|||
return getContainingScope( (IASTStatement) node );
|
||||
} else if( node instanceof IASTTypeId ){
|
||||
node = node.getParent();
|
||||
if( node instanceof ICPPASTTemplateParameter )
|
||||
return CPPTemplates.getContainingScope( node );
|
||||
} else if( node instanceof IASTParameterDeclaration ){
|
||||
IASTNode parent = node.getParent();
|
||||
if( parent instanceof ICPPASTFunctionDeclarator ){
|
||||
|
@ -1366,6 +1368,8 @@ public class CPPVisitor {
|
|||
}
|
||||
|
||||
public static IType createType( IASTNode node ){
|
||||
if( node == null )
|
||||
return null;
|
||||
if( node instanceof IASTExpression )
|
||||
return getExpressionType( (IASTExpression) node );
|
||||
if( node instanceof IASTTypeId )
|
||||
|
|
Loading…
Add table
Reference in a new issue