1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 10:16:03 +02:00

207871: add limited support for integral non-type template arguments

This commit is contained in:
Andrew Ferguson 2008-05-28 18:18:54 +00:00
parent ce474b8bc1
commit 09295cf66e
23 changed files with 405 additions and 81 deletions

View file

@ -36,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
@ -45,6 +46,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
@ -2742,6 +2744,27 @@ public class AST2TemplateTests extends AST2BaseTest {
assertTrue(!Z.isSameType(X));
}
// template<class T, bool b> class A {public: class X {};};
// template<class T1> class A<T1,true> {public: class Y {};};
//
// class B {};
//
// A<B, false>::X x; //1
// A<B, true>::Y y; //2
//
// A<B, true>::X x; //3 should be an error
// A<B, false>::Y y; //4 should be an error
public void testNonTypeBooleanArgumentDisambiguation() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ICPPClassType X= ba.assertNonProblem("X x; //1", 1, ICPPClassType.class);
ICPPClassType Y= ba.assertNonProblem("Y y; //2", 1, ICPPClassType.class);
ba.assertProblem("X x; //3", 1);
ba.assertProblem("Y y; //4", 1);
assertTrue(!X.isSameType(Y));
}
// template <int x>
// class C {
// public:
@ -2762,8 +2785,35 @@ public class AST2TemplateTests extends AST2BaseTest {
// bar(t);
// baz();
// }
public void _testBug207871() throws Exception {
public void testBug207871() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ICPPVariable _256= ba.assertNonProblem("_256=0x100", 4, ICPPVariable.class);
IQualifierType qt1= assertInstance(_256.getType(), IQualifierType.class);
ICPPBasicType bt1= assertInstance(qt1.getType(), ICPPBasicType.class);
assertEquals(256, CPPVisitor.parseIntegral(bt1.getValue().toString()).intValue());
ICPPVariable t= ba.assertNonProblem("t;", 1, ICPPVariable.class);
ICPPTemplateInstance ci1= assertInstance(t.getType(), ICPPTemplateInstance.class, ICPPClassType.class);
ObjectMap args1= ci1.getArgumentMap();
assertEquals(1, args1.size());
assertInstance(args1.keyAt(0), ICPPTemplateNonTypeParameter.class);
// non-type arguments are currently modelled as a type with attached expression
ICPPBasicType bt0= assertInstance(args1.getAt(0), ICPPBasicType.class);
assertEquals(bt0.getType(), IBasicType.t_int);
assertEquals(256, CPPVisitor.parseIntegral(bt0.getValue().toString()).intValue());
ICPPTemplateInstance ct= ba.assertNonProblem("C<_256> ", 7, ICPPTemplateInstance.class, ICPPClassType.class);
ObjectMap args= ct.getArgumentMap();
assertEquals(1, args.size());
assertInstance(args.keyAt(0), ICPPTemplateNonTypeParameter.class);
// non-type arguments are currently modelled as a type with attached expression
ICPPBasicType bt= assertInstance(args.getAt(0), ICPPBasicType.class);
assertEquals(bt.getType(), IBasicType.t_int);
assertEquals(256, CPPVisitor.parseIntegral(bt.getValue().toString()).intValue());
ba.assertNonProblem("foo(t)", 3);
ba.assertNonProblem("bar(t)", 3);
}

View file

@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/**
* @author dsteffle
@ -164,4 +165,34 @@ public class AST2UtilTests extends AST2BaseTest {
assertEquals(fooSignature, foo2Signature);
}
public void testParseIntegral() throws Exception {
assertEquals(0, CPPVisitor.parseIntegral("0").intValue());
assertEquals(0, CPPVisitor.parseIntegral("+0").intValue());
assertEquals(0, CPPVisitor.parseIntegral("-0").intValue());
assertEquals(0, CPPVisitor.parseIntegral("0x0").intValue());
assertEquals(0, CPPVisitor.parseIntegral("00").intValue());
assertEquals(0, CPPVisitor.parseIntegral("000").intValue());
assertEquals(0, CPPVisitor.parseIntegral("0L").intValue());
assertEquals(0, CPPVisitor.parseIntegral("0LL").intValue());
assertEquals(1, CPPVisitor.parseIntegral("1").intValue());
assertEquals(1, CPPVisitor.parseIntegral("01").intValue());
assertEquals(1, CPPVisitor.parseIntegral("0x1").intValue());
assertEquals(1, CPPVisitor.parseIntegral("+1").intValue());
assertEquals(1, CPPVisitor.parseIntegral("+01").intValue());
assertEquals(1, CPPVisitor.parseIntegral("+0x1").intValue());
assertEquals(-1, CPPVisitor.parseIntegral("-1").intValue());
assertEquals(-1, CPPVisitor.parseIntegral("-01").intValue());
assertEquals(-1, CPPVisitor.parseIntegral("-0x1").intValue());
assertEquals(-10, CPPVisitor.parseIntegral("-10").intValue());
assertEquals(-8, CPPVisitor.parseIntegral("-010").intValue());
assertEquals(-16, CPPVisitor.parseIntegral("-0x10").intValue());
assertEquals(-10, CPPVisitor.parseIntegral("-10LLL").intValue());
assertEquals(-8, CPPVisitor.parseIntegral("-010LLL").intValue());
assertEquals(-16, CPPVisitor.parseIntegral("-0x10LLL").intValue());
}
}

View file

@ -1211,7 +1211,6 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
assertEquals(((IBasicType)type).getType(), IBasicType.t_int);
}
// template<typename _Iterator> struct iterator_traits {
// typedef typename _Iterator::pointer pointer;
// };
@ -1286,7 +1285,7 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
// bar(t);
// baz();
// }
public void _testClassInstanceWithNonTypeArgument_207871() throws Exception {
public void testClassInstanceWithNonTypeArgument_207871() throws Exception {
ICPPTemplateInstance c256 = getBindingFromASTName("C<256>", 6, ICPPTemplateInstance.class, ICPPClassType.class);
ObjectMap args= c256.getArgumentMap();
assertEquals(1, args.size());
@ -1297,4 +1296,82 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
ICPPFunction foo = getBindingFromASTName("foo(t)", 3, ICPPFunction.class);
ICPPFunction bar = getBindingFromASTName("bar(t)", 3, ICPPFunction.class);
}
// template<class T, int x> class A {public: class X {};};
// template<class T1> class A<T1,'y'> {public: class Y {};};
// template<class T2> class A<T2,'z'> {public: class Z {};};
//
// class B {};
// A<B, 'x'>::X x;
// A<B, 'y'>::Y y;
// A<B, 'z'>::Z z;
public void testNonTypeCharArgumentDisambiguation() throws Exception {
ICPPClassType b2= getBindingFromASTName("A<B, 'x'>", 9, ICPPClassType.class, ICPPTemplateInstance.class);
ICPPClassType b3= getBindingFromASTName("A<B, 'y'>", 9, ICPPClassType.class, ICPPTemplateInstance.class);
ICPPClassType b4= getBindingFromASTName("A<B, 'z'>", 9, ICPPClassType.class, ICPPTemplateInstance.class);
assertTrue(!b2.isSameType(b3));
assertTrue(!b3.isSameType(b4));
assertTrue(!b4.isSameType(b2));
ICPPClassType X= getBindingFromASTName("X x", 1, ICPPClassType.class);
ICPPClassType Y= getBindingFromASTName("Y y", 1, ICPPClassType.class);
ICPPClassType Z= getBindingFromASTName("Z z", 1, ICPPClassType.class);
assertTrue(!X.isSameType(Y));
assertTrue(!Y.isSameType(Z));
assertTrue(!Z.isSameType(X));
}
// template<class T, bool b> class A {public: class X {};};
// template<class T1> class A<T1,true> {public: class Y {};};
//
// class B {};
// A<B, false>::X x; //1
// A<B, true>::Y y; //2
//
// A<B, true>::X x; //3 should be an error
// A<B, false>::Y y; //4 should be an error
public void testNonTypeBooleanArgumentDisambiguation() throws Exception {
ICPPClassType X= getBindingFromASTName("X x; //1", 1, ICPPClassType.class);
ICPPClassType Y= getBindingFromASTName("Y y; //2", 1, ICPPClassType.class);
getProblemFromASTName("X x; //3", 1);
getProblemFromASTName("Y y; //4", 1);
assertTrue(!X.isSameType(Y));
}
// template<int x> class A {};
// template<> class A<5> {public: class B{};};
//
// const int FIVE= 5;
// const int CINQ= FIVE;
// const int FUNF= CINQ;
// void refs() {
// A<FIVE> a5a;
// A<CINQ> a5b;
// A<FUNF> a5c;
// A<5> a5d;
// A<1> a1;
// }
public void testConstantPropogationFromHeader() throws Exception {
ICPPClassType a5a= getBindingFromASTName("A<FIVE>", 7, ICPPClassType.class, ICPPSpecialization.class);
ICPPClassType a5b= getBindingFromASTName("A<CINQ>", 7, ICPPClassType.class, ICPPSpecialization.class);
ICPPClassType a5c= getBindingFromASTName("A<FUNF>", 7, ICPPClassType.class, ICPPSpecialization.class);
ICPPClassType a5d= getBindingFromASTName("A<5>", 4, ICPPClassType.class, ICPPSpecialization.class);
ICPPClassType a1= getBindingFromASTName("A<1>", 4, ICPPClassType.class, ICPPTemplateInstance.class);
assertTrue(a5a.isSameType(a5b));
assertTrue(a5b.isSameType(a5c));
assertTrue(a5c.isSameType(a5d));
assertTrue(a5d.isSameType(a5a));
assertTrue(!a1.isSameType(a5a));
assertTrue(!a1.isSameType(a5b));
assertTrue(!a1.isSameType(a5c));
assertTrue(!a1.isSameType(a5d));
}
}

View file

@ -13,7 +13,14 @@ package org.eclipse.cdt.internal.pdom.tests;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMNode;
import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.cdt.internal.core.index.CIndex;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.pdom.PDOM;
@ -45,6 +52,17 @@ public class PDOMPrettyPrinter implements IPDOMVisitor {
PDOMBinding binding= (PDOMBinding) node;
sb.append(" "+binding.getRecord());
}
if(node instanceof ICPPVariable) {
try {
IType type= SemanticUtil.getUltimateTypeUptoPointers(((ICPPVariable)node).getType());
if(type instanceof ICPPBasicType) {
IASTExpression e1= ((IBasicType)type).getValue();
sb.append(" value="+(e1==null?"null":e1.toString()));
}
} catch(DOMException de) {
sb.append(" "+de.getMessage());
}
}
System.out.println(sb);
return true;
}

View file

@ -137,7 +137,7 @@ public class CPPClassInstance extends CPPInstance implements ICPPClassType {
for (int i = 0; i < m1.size(); i++) {
IType t1 = (IType) m1.getAt(i);
IType t2 = (IType) m2.getAt(i);
if (t1 == null || !t1.isSameType(t2))
if (!CPPTemplates.isSameTemplateArgument(t1, t2))
return false;
}
return true;

View file

@ -75,7 +75,7 @@ public class CPPClassTemplateSpecialization extends CPPClassSpecialization
if (args.length == arguments.length) {
int j = 0;
for(; j < args.length; j++) {
if (!(args[j].isSameType(arguments[j])))
if (!CPPTemplates.isSameTemplateArgument(args[j], arguments[j]))
break;
}
if (j == args.length) {

View file

@ -77,7 +77,7 @@ public class CPPDeferredClassInstance extends CPPUnknownClass implements ICPPDef
return false;
for (int i= 0; i < lhsArgs.length; i++) {
if (!lhsArgs[i].isSameType(rhsArgs[i]))
if (!CPPTemplates.isSameTemplateArgument(lhsArgs[i],rhsArgs[i]))
return false;
}
}

View file

@ -168,7 +168,7 @@ public class CPPFunctionInstance extends CPPInstance implements ICPPFunction, IC
for( int i = 0; i < m1.size(); i++ ){
IType t1 = (IType) m1.getAt( i );
IType t2 = (IType) m2.getAt( i );
if( t1 == null || ! t1.isSameType( t2 ) )
if(!CPPTemplates.isSameTemplateArgument(t1, t2))
return false;
}
return true;

View file

@ -55,7 +55,7 @@ public class CPPFunctionTemplateSpecialization extends CPPFunctionSpecialization
if( args.length == arguments.length ){
int j = 0;
for(; j < args.length; j++) {
if( !( args[j].isSameType( arguments[j] ) ) )
if(!CPPTemplates.isSameTemplateArgument(args[j], arguments[j]))
break;
}
if( j == args.length ){

View file

@ -139,7 +139,7 @@ public abstract class CPPTemplateDefinition extends PlatformObject implements IC
if (args.length == arguments.length) {
int j = 0;
for (; j < args.length; j++) {
if (!args[j].isSameType(arguments[j]))
if (!CPPTemplates.isSameTemplateArgument(args[j], arguments[j]))
break;
}
if (j == args.length) {

View file

@ -73,7 +73,7 @@ public class CPPUnknownClassInstance extends CPPUnknownClass implements ICPPUnkn
return false;
for (int i= 0; i < lhsArgs.length; i++) {
if (!lhsArgs[i].isSameType(rhsArgs[i]))
if (!CPPTemplates.isSameTemplateArgument(lhsArgs[i],rhsArgs[i]))
return false;
}
}

View file

@ -13,8 +13,10 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import java.math.BigInteger;
import java.util.LinkedList;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
@ -23,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
@ -576,7 +579,7 @@ public class CPPTemplates {
IType t = (IType) map.get(param);
if (arg == null) {
arg = t;
} else if (!t.isSameType(arg)) {
} else if (!CPPTemplates.isSameTemplateArgument(t, arg)) {
continue outer;
}
} else if (arg == null || !matchTemplateParameterAndArgument(param, arg, map)) {
@ -1055,15 +1058,13 @@ public class CPPTemplates {
if (name instanceof ICPPASTTemplateId) {
if (definition instanceof ICPPClassTemplatePartialSpecialization) {
ICPPClassTemplatePartialSpecialization spec = (ICPPClassTemplatePartialSpecialization) definition;
IASTNode[] args = ((ICPPASTTemplateId) name).getTemplateArguments();
IType[] args= createTemplateArgumentArray((ICPPASTTemplateId)name);
try {
IType[] specArgs = spec.getArguments();
if (args.length == specArgs.length) {
int i = 0;
for (; i < args.length; i++) {
IType t1 = specArgs[i];
IType t2 = CPPVisitor.createType(args[i]);
if (isSameTemplateArgument(t1, t2))
if (isSameTemplateArgument(specArgs[i], args[i]))
continue;
break;
}
@ -1087,19 +1088,24 @@ public class CPPTemplates {
}
/**
* @param argA
* @param argB
* @param argA may be null
* @param argB may be null
* @return whether the two specified template arguments are the same
* @throws DOMException
*/
private static final boolean isSameTemplateArgument(IType argA, IType argB) throws DOMException {
public static final boolean isSameTemplateArgument(IType argA, IType argB) {
// special case treatment for non-type integral parameters
if(argA instanceof ICPPBasicType && argB instanceof ICPPBasicType) {
IASTExpression eA= ((ICPPBasicType) argA).getValue();
IASTExpression eB= ((ICPPBasicType) argB).getValue();
if(eA != null && eB != null) {
return expressionsEquivalent(eA, eB);
} else if(eA == null ^ eB == null) {
try {
IASTExpression eA= ((ICPPBasicType) argA).getValue();
IASTExpression eB= ((ICPPBasicType) argB).getValue();
if(eA != null && eB != null) {
// TODO - we should normalize template arguments
// rather than check their original expressions
// are equivalent.
return argA.isSameType(argB) && expressionsEquivalent(eA, eB);
}
} catch(DOMException de) {
CCorePlugin.log(de);
return false;
}
}
@ -1118,7 +1124,17 @@ public class CPPTemplates {
IASTNode[] params= id.getTemplateArguments();
result = new IType[params.length];
for (int i = 0; i < params.length; i++) {
IType type= CPPVisitor.createType(params[i]);
IASTNode param= params[i];
/*
* id-expression's which resolve to const variables can be
* modeled by the type of the initialized expression (which
* will include its value)
*/
if(param instanceof IASTIdExpression) {
param= CPPVisitor.reverseConstantPropogationLookup((IASTIdExpression)param);
}
IType type= CPPVisitor.createType(param);
// prevent null pointer exception when the type cannot be determined
// happens when templates with still ambiguous template-ids are accessed during
// resolution of other ambiguities.
@ -1171,13 +1187,13 @@ public class CPPTemplates {
int size = templates.size();
int numTemplateArgs = 0;
IASTNode[] templateArguments = null;
IType[] templateArguments = null;
if (name instanceof ICPPASTTemplateId) {
templateArguments = ((ICPPASTTemplateId) name).getTemplateArguments();
templateArguments = createTemplateArgumentArray((ICPPASTTemplateId) name);
numTemplateArgs = templateArguments.length;
}
IType[] fnArgs = createTypeArray(functionArguments);
IType[] fnArgs= createTypeArray(functionArguments);
outer: for (int idx = 0; idx < size; idx++) {
ICPPFunctionTemplate template = (ICPPFunctionTemplate) templates.keyAt(idx);
@ -1201,11 +1217,11 @@ public class CPPTemplates {
IType[] instanceArgs = null;
for (int i = 0; i < numTemplateParams; i++) {
IType arg = (i < numTemplateArgs && templateArguments != null) ? CPPVisitor.createType(templateArguments[i]) : null;
IType arg = (i < numTemplateArgs && templateArguments != null) ? templateArguments[i] : null;
IType mapped = (IType) map.get(templateParams[i]);
if (arg != null && mapped != null) {
if (arg.isSameType(mapped))
if (arg.isSameType(mapped)) // compare as IType: 'mapped' is not a template argument
instanceArgs = (IType[]) ArrayUtil.append(IType.class, instanceArgs, arg);
else
continue outer;
@ -1340,12 +1356,26 @@ public class CPPTemplates {
return result;
}
static private boolean expressionsEquivalent(IASTExpression p, IASTExpression a) {
if (p == null)
private static boolean expressionsEquivalent(IASTExpression e1, IASTExpression e2) {
if (e1 == null)
return true;
if (p instanceof IASTLiteralExpression && a instanceof IASTLiteralExpression) {
return p.toString().equals(a.toString ());
e1= CPPVisitor.reverseConstantPropogationLookup(e1);
e2= CPPVisitor.reverseConstantPropogationLookup(e2);
if (e1 instanceof IASTLiteralExpression && e2 instanceof IASTLiteralExpression) {
IType t1= e1.getExpressionType();
IType t2= e2.getExpressionType();
try {
if(t1 instanceof ICPPBasicType && t2 instanceof ICPPBasicType) {
BigInteger i1= CPPVisitor.parseIntegral(e1.toString());
BigInteger i2= CPPVisitor.parseIntegral(e2.toString());
return i1.equals(i2);
}
} catch(NumberFormatException nfe) {
/* fall through */
}
return e1.toString().equals(e2.toString());
}
return false;
}

View file

@ -16,6 +16,9 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers;
import java.math.BigInteger;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.DOMException;
@ -136,12 +139,14 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointer;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointerToMember;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
@ -1609,6 +1614,16 @@ public class CPPVisitor {
if (nested != null) {
return createType(type, nested);
}
// Currently, CPPBasicType objects are also used to represent non-type template argument
// values. We must ensure the initializer expression is attached to the type if available.
if(declarator.getInitializer() instanceof IASTInitializerExpression) {
IType utype= getUltimateTypeUptoPointers(baseType);
if(utype instanceof CPPBasicType) {
((CPPBasicType)utype).setValue(((IASTInitializerExpression) declarator.getInitializer()).getExpression());
}
}
return type;
}
@ -2344,4 +2359,84 @@ public class CPPVisitor {
}
return false;
}
/**
* @param integral
* @return the (non-null) integer value of the specified literal
* @throws NumberFormatException
*/
/*
* Currently unsigned (U,u) is stripped and ignored.
*/
public static BigInteger parseIntegral(String integral) {
int radix= 10;
if(integral.length() == 3
&& integral.charAt(0) == '\''
&& integral.charAt(2) == '\'') {
String lo= Long.toString(Character.getNumericValue(integral.charAt(1)));
return new BigInteger(lo);
} else if(Keywords.TRUE.equals(integral)) {
return BigInteger.ONE;
} else if(Keywords.FALSE.equals(integral)) {
return BigInteger.ZERO;
}
int start=0, end= integral.length();
boolean negate= integral.charAt(start)=='-';
if(negate || integral.charAt(start)=='+') {
start++;
}
if(start<integral.length() && integral.charAt(start) == '0') {
if(start+1<integral.length()) {
if(integral.charAt(start+1) == 'x') {
start+=2;
radix= 16;
} else {
radix= 8;
}
}
}
for(end--; end>0; end--) {
final char c= integral.charAt(end);
if(c != 'L' && c!='l' && c!='U' && c!='u') {
break;
}
}
integral= integral.substring(start, end+1);
BigInteger result= new BigInteger(integral, radix);
return negate ? result.negate() : result;
}
/**
* @param e1
* @return the first non id-expression by following values assigned to basic types.
*/
public static final IASTExpression reverseConstantPropogationLookup(IASTExpression e1) {
try {
for(int i=0; e1 instanceof IASTIdExpression && i<8; i++) {
IBinding b1= ((IASTIdExpression)e1).getName().resolveBinding();
if(b1 instanceof ICPPVariable) {
ICPPVariable var= (ICPPVariable) b1;
IType t1= SemanticUtil.getUltimateTypeViaTypedefs(var.getType());
if(t1 instanceof IQualifierType) {
IQualifierType qt= (IQualifierType) t1;
if(qt.isConst()) {
t1= SemanticUtil.getUltimateTypeViaTypedefs(qt.getType());
if(t1 instanceof ICPPBasicType) {
e1= ((ICPPBasicType)t1).getValue();
}
}
}
}
}
} catch(DOMException de) {
CCorePlugin.log(de);
}
return e1;
}
}

View file

@ -104,7 +104,7 @@ public class PDOM extends PlatformObject implements IPDOM {
private static int version(int major, int minor) {
return major << 16 + minor;
}
public static final int MAJOR_VERSION = 59;
public static final int MAJOR_VERSION = 60;
public static final int MINOR_VERSION = 0; // minor versions must be compatible
public static final int CURRENT_VERSION= version(MAJOR_VERSION, MINOR_VERSION);
@ -173,6 +173,7 @@ public class PDOM extends PlatformObject implements IPDOM {
* 57.0 - macro references (bug 156561)
* 58.0 - non-type parameters (bug 207840)
* 59.0 - changed modeling of deferred class instances (bug 229218)
* 60.0 - store integral values with basic types (bug 207871)
*/
public static final int LINKAGES = Database.DATA_AREA;

View file

@ -8,6 +8,7 @@
* Contributors:
* QNX - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
@ -16,10 +17,15 @@ import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.index.IIndexType;
import org.eclipse.cdt.internal.core.pdom.PDOM;
@ -32,12 +38,14 @@ import org.eclipse.core.runtime.CoreException;
*
*/
class PDOMCPPBasicType extends PDOMNode implements ICPPBasicType, IIndexType {
public static final int TYPE_ID = PDOMNode.RECORD_SIZE + 0; // short
public static final int FLAGS = PDOMNode.RECORD_SIZE + 2; // short
private static final int TYPE_ID = PDOMNode.RECORD_SIZE + 0; // short
private static final int QUALIFIER_FLAGS = PDOMNode.RECORD_SIZE + 2; // short
private static final int INTEGRAL = PDOMNode.RECORD_SIZE + 4; // int
private static final int INTERNAL_FLAGS = PDOMNode.RECORD_SIZE + 8; // byte
@SuppressWarnings("hiding")
public static final int RECORD_SIZE = PDOMNode.RECORD_SIZE + 4;
private static final int RECORD_SIZE = PDOMNode.RECORD_SIZE + 9;
protected short fFlags= -1;
@ -55,7 +63,20 @@ class PDOMCPPBasicType extends PDOMNode implements ICPPBasicType, IIndexType {
fFlags= flags;
Database db = pdom.getDB();
db.putShort(record + TYPE_ID, getTypeCode(type));
db.putShort(record + FLAGS, flags);
try {
if(type.getValue() != null) {
IASTExpression e= CPPVisitor.reverseConstantPropogationLookup(type.getValue());
if(e != null) {
db.putInt(record + INTEGRAL, CPPVisitor.parseIntegral(e.toString()).intValue());
db.putByte(record + INTERNAL_FLAGS, (byte)1);
}
}
} catch(DOMException de) {
CCorePlugin.log(de);
} catch(NumberFormatException nfe) {
/* fall-through */
}
db.putShort(record + QUALIFIER_FLAGS, flags);
}
private short getTypeCode(ICPPBasicType type) {
@ -103,15 +124,37 @@ class PDOMCPPBasicType extends PDOMNode implements ICPPBasicType, IIndexType {
}
public IASTExpression getValue() throws DOMException {
// Returning null for now, not sure what needs to be here if anything
// Values only seem to be used at type resolution time.
try {
/*
* If the expression was an integral we can emulate what would
* have been returned in a limited way.
*/
if(pdom.getDB().getByte(record + INTERNAL_FLAGS) != 0) {
int integral= pdom.getDB().getInt(record + INTEGRAL);
String literal= Integer.toString(integral);
int type= getType();
if(type == t_char) {
return new CPPASTLiteralExpression(IASTLiteralExpression.lk_char_constant, literal);
} else if(type == t_int) {
return new CPPASTLiteralExpression(IASTLiteralExpression.lk_integer_constant, literal);
} else if(type == t_bool) {
if(integral == 0) {
return new CPPASTLiteralExpression(ICPPASTLiteralExpression.lk_false, Keywords.FALSE);
} else {
return new CPPASTLiteralExpression(ICPPASTLiteralExpression.lk_true, Keywords.TRUE);
}
}
}
} catch(CoreException ce) {
CCorePlugin.log(ce);
}
return null;
}
public int getQualifierBits() {
if (fFlags == -1) {
try {
fFlags= pdom.getDB().getShort(record + FLAGS);
fFlags= pdom.getDB().getShort(record + QUALIFIER_FLAGS);
}
catch (CoreException e) {
CCorePlugin.log(e);

View file

@ -151,7 +151,7 @@ class PDOMCPPClassInstance extends PDOMCPPInstance implements
for (int i = 0; i < m1.size(); i++) {
IType t1 = (IType) m1.getAt(i);
IType t2 = (IType) m2.getAt(i);
if (t1 == null || !t1.isSameType(t2))
if (!CPPTemplates.isSameTemplateArgument(t1, t2))
return false;
}
return true;

View file

@ -30,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
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.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
import org.eclipse.cdt.core.index.IIndexBinding;
@ -369,6 +370,12 @@ class PDOMCPPClassTemplate extends PDOMCPPClassType
if (p instanceof IType && op instanceof IType) {
same &= (((IType)p).isSameType((IType)op));
} else {
if(p instanceof ICPPTemplateNonTypeParameter
&& op instanceof ICPPTemplateNonTypeParameter) {
IType pt= ((ICPPTemplateNonTypeParameter)p).getType();
IType opt= ((ICPPTemplateNonTypeParameter)op).getType();
return pt!=null && opt!=null ? pt.isSameType(opt) : pt == opt;
}
return false;
}
}

View file

@ -274,7 +274,7 @@ class PDOMCPPClassTemplatePartialSpecialization extends
for( int i = 0; i < m1.size(); i++ ){
IType t1 = (IType) m1.getAt( i );
IType t2 = (IType) m2.getAt( i );
if( t1 == null || ! t1.isSameType( t2 ) )
if(!CPPTemplates.isSameTemplateArgument(t1, t2 ))
return false;
}
return true;

View file

@ -116,7 +116,7 @@ class PDOMCPPDeferredClassInstance extends PDOMCPPInstance implements ICPPDeferr
return false;
for (int i= 0; i < lhsArgs.length; i++) {
if (!lhsArgs[i].isSameType(rhsArgs[i]))
if (!CPPTemplates.isSameTemplateArgument(lhsArgs[i], rhsArgs[i]))
return false;
}
}

View file

@ -19,6 +19,7 @@ import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.db.PDOMNodeLinkedList;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
@ -92,7 +93,7 @@ abstract class PDOMCPPInstance extends PDOMCPPSpecialization implements ICPPTemp
if (args.length == arguments.length) {
int i = 0;
for (; i < args.length; i++) {
if (!(args[i].isSameType(arguments[i])))
if (!CPPTemplates.isSameTemplateArgument(args[i], arguments[i]))
break;
}
return i == args.length;

View file

@ -27,6 +27,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.index.IIndexScope;
import org.eclipse.cdt.internal.core.index.IndexCPPSignatureUtil;
import org.eclipse.cdt.internal.core.pdom.PDOM;
@ -180,7 +181,7 @@ abstract class PDOMCPPSpecialization extends PDOMCPPBinding implements
if (args.length == arguments.length) {
int i = 0;
for (; i < args.length; i++) {
if (args[i] == null || !args[i].isSameType(arguments[i]))
if (!CPPTemplates.isSameTemplateArgument(args[i], arguments[i]))
break;
}
return i == args.length;

View file

@ -13,17 +13,11 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.index.IIndexType;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.db.PDOMNodeLinkedList;
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner;
@ -34,7 +28,7 @@ import org.eclipse.core.runtime.CoreException;
* @author Bryan Wilkinson
*/
class PDOMCPPTemplateNonTypeParameter extends PDOMCPPVariable implements IPDOMMemberOwner,
ICPPTemplateNonTypeParameter, IIndexType {
ICPPTemplateNonTypeParameter {
private static final int MEMBERLIST = PDOMCPPVariable.RECORD_SIZE;
@ -79,30 +73,6 @@ class PDOMCPPTemplateNonTypeParameter extends PDOMCPPVariable implements IPDOMMe
list.accept(visitor);
}
public boolean isSameType(IType type) {
if (type instanceof ITypedef) {
return type.isSameType(this);
}
if (type instanceof PDOMNode) {
PDOMNode node= (PDOMNode) type;
if (node.getPDOM() == getPDOM()) {
return node.getRecord() == getRecord();
}
}
if (type instanceof ICPPTemplateNonTypeParameter && !(type instanceof ProblemBinding)) {
ICPPTemplateNonTypeParameter ttp= (ICPPTemplateNonTypeParameter) type;
try {
char[][] ttpName= ttp.getQualifiedNameCharArray();
return hasQualifiedName(ttpName, ttpName.length - 1);
} catch (DOMException e) {
CCorePlugin.log(e);
}
}
return false;
}
public ICPPBinding getParameterOwner() throws CoreException {
return (ICPPBinding) getParentBinding();
}

View file

@ -147,7 +147,7 @@ class PDOMCPPUnknownClassInstance extends PDOMCPPUnknownClassType implements ICP
return false;
for (int i= 0; i < lhsArgs.length; i++) {
if (!lhsArgs[i].isSameType(rhsArgs[i]))
if (!CPPTemplates.isSameTemplateArgument(lhsArgs[i], rhsArgs[i]))
return false;
}
}