1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-30 04:15:35 +02:00

Rework of standard conversion sequence, bug 263159.

This commit is contained in:
Markus Schorn 2009-02-09 11:43:21 +00:00
parent 02ecde30f4
commit 7e4bb073a8
12 changed files with 491 additions and 503 deletions

View file

@ -5941,7 +5941,7 @@ public class AST2CPPTests extends AST2BaseTest {
// f3(r); // f3(r);
// f4(s); // f4(s);
// } // }
public void _testArrayToPointerConversion() throws Exception { public void testArrayToPointerConversion() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertNonProblem("f1(p)", 2, ICPPFunction.class); ba.assertNonProblem("f1(p)", 2, ICPPFunction.class);
ba.assertProblem("f2(q)", 2); ba.assertProblem("f2(q)", 2);
@ -6619,7 +6619,7 @@ public class AST2CPPTests extends AST2BaseTest {
// void test() { // void test() {
// f(a()); // f(a());
// } // }
public void _testBug263152_1() throws Exception { public void testBug263152_1() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertProblem("f(a())", 1); ba.assertProblem("f(a())", 1);
} }
@ -6635,7 +6635,7 @@ public class AST2CPPTests extends AST2BaseTest {
// void test(B p) { // void test(B p) {
// p.m(a()); // p.m(a());
// } // }
public void _testBug263152_2() throws Exception { public void testBug263152_2() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertNonProblem("m(a())", 1, ICPPMethod.class); ba.assertNonProblem("m(a())", 1, ICPPMethod.class);
} }
@ -6699,7 +6699,7 @@ public class AST2CPPTests extends AST2BaseTest {
// fip(0); // fip(0);
// fia(0); // fia(0);
// } // }
public void _testNonPointerToPointerConversion_263707() throws Exception { public void testNonPointerToPointerConversion_263707() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertProblem("fip(1)", 3); ba.assertProblem("fip(1)", 3);
ba.assertProblem("fia(1)", 3); ba.assertProblem("fia(1)", 3);

View file

@ -228,21 +228,25 @@ public class ASTTypeUtil {
} }
result.append(Keywords.cpRBRACKET); result.append(Keywords.cpRBRACKET);
} else if (type instanceof IBasicType) { } else if (type instanceof IBasicType) {
IBasicType basicType= (IBasicType) type;
try { try {
if (((IBasicType) type).isSigned()) { if (basicType.isSigned()) {
result.append(Keywords.SIGNED); needSpace = true; // 3.9.1.2: signed integer types
} else if (((IBasicType) type).isUnsigned()) { if (!normalize || basicType.getType() == IBasicType.t_char) {
result.append(Keywords.SIGNED); needSpace = true;
}
} else if (basicType.isUnsigned()) {
if (needSpace) { if (needSpace) {
result.append(SPACE); needSpace = false; result.append(SPACE); needSpace = false;
} }
result.append(Keywords.UNSIGNED); needSpace = true; result.append(Keywords.UNSIGNED); needSpace = true;
} }
if (((IBasicType) type).isLong()) { if (basicType.isLong()) {
if (needSpace) { if (needSpace) {
result.append(SPACE); needSpace = false; result.append(SPACE); needSpace = false;
} }
result.append(Keywords.LONG); needSpace = true; result.append(Keywords.LONG); needSpace = true;
} else if (((IBasicType) type).isShort()) { } else if (basicType.isShort()) {
if (needSpace) { if (needSpace) {
result.append(SPACE); needSpace = false; result.append(SPACE); needSpace = false;
} }
@ -316,7 +320,7 @@ public class ASTTypeUtil {
} }
try { try {
switch (((IBasicType) type).getType()) { switch (basicType.getType()) {
case IBasicType.t_char: case IBasicType.t_char:
if (needSpace) result.append(SPACE); if (needSpace) result.append(SPACE);
result.append(Keywords.CHAR); result.append(Keywords.CHAR);

View file

@ -103,7 +103,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
case lk_string_literal: case lk_string_literal:
IType type = new CPPBasicType(IBasicType.t_char, 0, this); IType type = new CPPBasicType(IBasicType.t_char, 0, this);
type = new CPPQualifierType(type, true, false); type = new CPPQualifierType(type, true, false);
return new CPPPointerType(type); return new CPPArrayType(type);
} }
return null; return null;
} }

View file

@ -59,6 +59,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/** /**
* Base implementation for c++ scopes. * Base implementation for c++ scopes.
@ -100,7 +101,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
char[] className = name.getLookupKey(); char[] className = name.getLookupKey();
IParameter[] voidPs = new IParameter[] { new CPPParameter(CPPSemantics.VOID_TYPE) }; IParameter[] voidPs = new IParameter[] { new CPPParameter(CPPSemantics.VOID_TYPE) };
IType pType = new CPPReferenceType(new CPPQualifierType(clsType, true, false)); IType pType = new CPPReferenceType(SemanticUtil.addQualifiers(clsType, true, false));
IParameter[] ps = new IParameter[] { new CPPParameter(pType) }; IParameter[] ps = new IParameter[] { new CPPParameter(pType) };
int i= 0; int i= 0;

View file

@ -32,6 +32,7 @@ import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.PlatformObject;
/** /**
@ -178,7 +179,8 @@ public class CPPParameter extends PlatformObject implements ICPPParameter, ICPPI
*/ */
public IType getType() { public IType getType() {
if (type == null && declarations != null) { if (type == null && declarations != null) {
type = CPPVisitor.createType((IASTDeclarator) declarations[0].getParent()); IType t= CPPVisitor.createType((IASTDeclarator) declarations[0].getParent());
type= SemanticUtil.adjustParameterType(t, false);
} }
return type; return type;
} }

View file

@ -19,7 +19,6 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
import org.eclipse.cdt.internal.core.index.IIndexType; import org.eclipse.cdt.internal.core.index.IIndexType;
@ -40,7 +39,7 @@ public class CPPPointerToMemberType extends CPPPointerType implements ICPPPointe
this.operator = operator; this.operator = operator;
} }
public CPPPointerToMemberType(IType type, ICPPClassType thisType, boolean isConst, boolean isVolatile) { public CPPPointerToMemberType(IType type, IType thisType, boolean isConst, boolean isVolatile) {
super(type, isConst, isVolatile); super(type, isConst, isVolatile);
this.classType = thisType; this.classType = thisType;
} }

View file

@ -146,7 +146,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownBinding;
@ -1974,10 +1973,7 @@ public class CPPSemantics {
if (owner instanceof ICPPClassTemplate) { if (owner instanceof ICPPClassTemplate) {
owner= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) owner); owner= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) owner);
} }
IType implicitType= owner; IType implicitType= SemanticUtil.addQualifiers(owner, ftype.isConst(), ftype.isVolatile());
if (ftype.isConst() || ftype.isVolatile()) {
implicitType = new CPPQualifierType(implicitType, ftype.isConst(), ftype.isVolatile());
}
result[0]= new CPPReferenceType(implicitType); result[0]= new CPPReferenceType(implicitType);
return result; return result;
} }
@ -2507,9 +2503,7 @@ public class CPPSemantics {
private static ICPPVariable createVariable(IASTName name, final IType type, final boolean isConst, final boolean isVolatile) { private static ICPPVariable createVariable(IASTName name, final IType type, final boolean isConst, final boolean isVolatile) {
return new CPPVariable(name) { return new CPPVariable(name) {
@Override public IType getType() { @Override public IType getType() {
if (isConst || isVolatile) return SemanticUtil.addQualifiers(type, isConst, isVolatile);
return new CPPQualifierType(type, isConst, isVolatile);
return type;
} }
}; };
} }

View file

@ -822,7 +822,7 @@ public class CPPTemplates {
IType newMemberOfClass = instantiateType(memberOfClass, tpMap, within); IType newMemberOfClass = instantiateType(memberOfClass, tpMap, within);
if (newNestedType != nestedType || newMemberOfClass != memberOfClass) { if (newNestedType != nestedType || newMemberOfClass != memberOfClass) {
if (newMemberOfClass instanceof ICPPClassType) { if (newMemberOfClass instanceof ICPPClassType) {
return new CPPPointerToMemberType(newNestedType, (ICPPClassType) newMemberOfClass, return new CPPPointerToMemberType(newNestedType, newMemberOfClass,
ptm.isConst(), ptm.isVolatile()); ptm.isConst(), ptm.isVolatile());
} }
return type; return type;
@ -1407,7 +1407,7 @@ public class CPPTemplates {
IType par= instPars[j]; IType par= instPars[j];
if (isDependentType(par)) { if (isDependentType(par)) {
// 14.8.2.1 // 14.8.2.1
par= SemanticUtil.adjustParameterType(par); par= SemanticUtil.adjustParameterType(par, true);
if (!deduceTemplateParameterMap(par, fnArgs[j], map)) { if (!deduceTemplateParameterMap(par, fnArgs[j], map)) {
return false; return false;
} }

View file

@ -1532,7 +1532,7 @@ public class CPPVisitor extends ASTQueries {
pt = createType(pDeclSpec); pt = createType(pDeclSpec);
pt = createType(pt, pDtor); pt = createType(pt, pDtor);
pt = SemanticUtil.adjustParameterType(pt); pt = SemanticUtil.adjustParameterType(pt, true);
pTypes[i] = pt; pTypes[i] = pt;
} }
@ -1766,8 +1766,7 @@ public class CPPVisitor extends ASTQueries {
if (type instanceof ICPPClassTemplate) { if (type instanceof ICPPClassTemplate) {
type= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) type); type= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) type);
} }
if (dtor.isConst() || dtor.isVolatile()) type = SemanticUtil.addQualifiers(type, dtor.isConst(), dtor.isVolatile());
type = new CPPQualifierType(type, dtor.isConst(), dtor.isVolatile());
type = new CPPPointerType(type); type = new CPPPointerType(type);
return type; return type;
} }

View file

@ -29,7 +29,6 @@ import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IQualifierType; import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; 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.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
@ -38,11 +37,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; 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.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
@ -78,8 +75,7 @@ public class Conversions {
if (source instanceof ICPPReferenceType) if (source instanceof ICPPReferenceType)
source= getNestedType(source, TYPEDEFS | REFERENCES); source= getNestedType(source, TYPEDEFS | REFERENCES);
IType T2= source instanceof IQualifierType ? IType T2= getNestedType(source, TYPEDEFS | REFERENCES | QUALIFIERS | PTR_QUALIFIERS);
getNestedType(((IQualifierType) source).getType(), TYPEDEFS | REFERENCES) : source;
// [8.5.3-5] Is an lvalue (but is not a bit-field), and "cv1 T1" is reference-compatible with "cv2 T2," // [8.5.3-5] Is an lvalue (but is not a bit-field), and "cv1 T1" is reference-compatible with "cv2 T2,"
if (lvalue) { if (lvalue) {
@ -150,43 +146,37 @@ public class Conversions {
} }
// [8.5.3-5] Direct binding failed - Otherwise // [8.5.3-5] Direct binding failed - Otherwise
boolean cv1isConst= getCVQualifier(cv1T1) == 1;
if (cv1isConst) {
if (!lvalue && T2 instanceof ICPPClassType) {
Cost cost= isReferenceCompatible(cv1T1, source);
if (cost != null)
return cost;
}
// 5 - Otherwise
// Otherwise, a temporary of type "cv1 T1" is created and initialized from
// the initializer expression using the rules for a non-reference copy
// initialization (8.5). The reference is then bound to the temporary.
boolean cv1isConst= false; // If T1 is reference-related to T2, cv1 must be the same cv-qualification as,
if (cv1T1 instanceof IQualifierType) { // or greater cv-qualification than, cv2; otherwise, the program is ill-formed.
cv1isConst= ((IQualifierType) cv1T1).isConst() && !((IQualifierType) cv1T1).isVolatile(); IType T1= getNestedType(cv1T1, TYPEDEFS | REFERENCES | QUALIFIERS | PTR_QUALIFIERS);
} else if (cv1T1 instanceof IPointerType) { boolean illformed= isReferenceRelated(T1, T2) >= 0 && compareQualifications(cv1T1, source) < 0;
cv1isConst= ((IPointerType) cv1T1).isConst() && !((IPointerType) cv1T1).isVolatile();
}
if (cv1isConst) {
if (!lvalue && source instanceof ICPPClassType) {
Cost cost= new Cost(source, target);
cost.rank= Cost.IDENTITY_RANK;
return cost;
} else {
// 5 - Otherwise
// Otherwise, a temporary of type "cv1 T1" is created and initialized from
// the initializer expression using the rules for a non-reference copy
// initialization (8.5). The reference is then bound to the temporary.
// If T1 is reference-related to T2, cv1 must be the same cv-qualification as,
// or greater cv-qualification than, cv2; otherwise, the program is ill-formed.
boolean illformed= isReferenceRelated(cv1T1, source) >= 0 && compareQualifications(cv1T1, source) < 0;
// We must do a non-reference initialization // We must do a non-reference initialization
if (!illformed) { if (!illformed) {
Cost cost= checkStandardConversionSequence(source, cv1T1, isImpliedObject); Cost cost= checkStandardConversionSequence(source, cv1T1, isImpliedObject);
// 12.3-4 At most one user-defined conversion is implicitly applied to // 12.3-4 At most one user-defined conversion is implicitly applied to
// a single value. (also prevents infinite loop) // a single value. (also prevents infinite loop)
if (allowUDC && (cost.rank == Cost.NO_MATCH_RANK || if (allowUDC && (cost.rank == Cost.NO_MATCH_RANK ||
cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) { cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) {
Cost temp = checkUserDefinedConversionSequence(source, cv1T1); Cost temp = checkUserDefinedConversionSequence(source, cv1T1);
if (temp != null) { if (temp != null) {
cost = temp; cost = temp;
}
} }
return cost;
} }
return cost;
} }
} }
return new Cost(source, cv1T1); return new Cost(source, cv1T1);
@ -208,8 +198,6 @@ public class Conversions {
* [3.9.3-4] Implements cv-ness (partial) comparison. There is a (partial) * [3.9.3-4] Implements cv-ness (partial) comparison. There is a (partial)
* ordering on cv-qualifiers, so that a type can be said to be more * ordering on cv-qualifiers, so that a type can be said to be more
* cv-qualified than another. * cv-qualified than another.
* @param cv1
* @param cv2
* @return <ul> * @return <ul>
* <li>GT 1 if cv1 is more qualified than cv2 * <li>GT 1 if cv1 is more qualified than cv2
* <li>EQ 0 if cv1 and cv2 are equally qualified * <li>EQ 0 if cv1 and cv2 are equally qualified
@ -217,40 +205,48 @@ public class Conversions {
* </ul> * </ul>
* @throws DOMException * @throws DOMException
*/ */
private static final int compareQualifications(IType cv1, IType cv2) throws DOMException { private static final int compareQualifications(IType t1, IType t2) throws DOMException {
boolean cv1Const= false, cv2Const= false, cv1Volatile= false, cv2Volatile= false; int cv1= getCVQualifier(t1);
if (cv1 instanceof IQualifierType) { int cv2= getCVQualifier(t2);
IQualifierType qt1= (IQualifierType) cv1;
cv1Const= qt1.isConst(); // same qualifications
cv1Volatile= qt1.isVolatile(); if (cv1 == cv2)
} else if (cv1 instanceof IPointerType) { return 0;
IPointerType pt1= (IPointerType) cv1;
cv1Const= pt1.isConst();
cv1Volatile= pt1.isVolatile();
}
if (cv2 instanceof IQualifierType) {
IQualifierType qt2= (IQualifierType) cv2;
cv2Const= qt2.isConst();
cv2Volatile= qt2.isVolatile();
} else if (cv2 instanceof IPointerType) {
IPointerType pt2= (IPointerType) cv2;
cv1Const= pt2.isConst();
cv1Volatile= pt2.isVolatile();
}
int cmpConst= cv1Const ? (cv2Const ? 0 : 1) : (!cv2Const ? 0 : -1);
int cmpVolatile= cv1Volatile ? (cv2Volatile ? 0 : 1) : (!cv2Volatile ? 0 : -1);
if (cmpConst == cmpVolatile) { // both are different but not comparable
return cmpConst; final int diffs= cv1 ^ cv2;
} else if (cmpConst != 0 && cmpVolatile == 0) { if (diffs == 3 && cv1 != 3 && cv2 != 3) {
return cmpConst; return -1;
} else if (cmpConst == 0 && cmpVolatile != 0) {
return cmpVolatile;
} }
return -1; return cv1-cv2;
} }
/**
* Returns 0 for no qualifier, 1 for const, 2 for volatile and 3 for const volatile.
*/
private static int getCVQualifier(IType t) {
if (t instanceof IQualifierType) {
int result= 0;
IQualifierType qt= (IQualifierType) t;
if (qt.isConst())
result= 1;
if (qt.isVolatile())
result |= 2;
return result;
}
if (t instanceof IPointerType) {
IPointerType pt= (IPointerType) t;
int result= 0;
if (pt.isConst())
result= 1;
if (pt.isVolatile())
result |= 2;
return result;
}
return 0;
}
/** /**
* [8.5.3] "cv1 T1" is reference-related to "cv2 T2" if T1 is the same type as T2, * [8.5.3] "cv1 T1" is reference-related to "cv2 T2" if T1 is the same type as T2,
* or T1 is a base class of T2. * or T1 is a base class of T2.
@ -264,11 +260,13 @@ public class Conversions {
// The way cv-qualification is currently modeled means // The way cv-qualification is currently modeled means
// we must cope with IPointerType objects separately. // we must cope with IPointerType objects separately.
if (t instanceof IPointerType && s instanceof IPointerType) { if (t instanceof IPointerType && s instanceof IPointerType) {
t= ((IPointerType) t).getType(); t= SemanticUtil.getNestedType(((IPointerType) t).getType(), TYPEDEFS | REFERENCES);
s= ((IPointerType) s).getType(); s= SemanticUtil.getNestedType(((IPointerType) s).getType(), TYPEDEFS | REFERENCES);
} else { } else {
t= t instanceof IQualifierType ? ((IQualifierType) t).getType() : t; if (t instanceof IQualifierType)
s= s instanceof IQualifierType ? ((IQualifierType) s).getType() : s; t= SemanticUtil.getNestedType(((IQualifierType) t).getType(), TYPEDEFS | REFERENCES);
if (s instanceof IQualifierType)
s= SemanticUtil.getNestedType(((IQualifierType) s).getType(), TYPEDEFS | REFERENCES);
if (t instanceof ICPPClassType && s instanceof ICPPClassType) { if (t instanceof ICPPClassType && s instanceof ICPPClassType) {
return calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, s, t); return calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, s, t);
@ -298,6 +296,7 @@ public class Conversions {
Cost cost= new Cost(cv2Source, cv1Target); Cost cost= new Cost(cv2Source, cv1Target);
cost.qualification= cmp > 0 ? Cost.CONVERSION_RANK : Cost.IDENTITY_RANK; cost.qualification= cmp > 0 ? Cost.CONVERSION_RANK : Cost.IDENTITY_RANK;
cost.conversion= inheritanceDist; cost.conversion= inheritanceDist;
cost.rank= Cost.IDENTITY_RANK;
return cost; return cost;
} }
@ -311,59 +310,27 @@ public class Conversions {
*/ */
protected static final Cost checkStandardConversionSequence(IType source, IType target, protected static final Cost checkStandardConversionSequence(IType source, IType target,
boolean isImplicitThis) throws DOMException { boolean isImplicitThis) throws DOMException {
Cost cost = lvalue_to_rvalue(source, target); final Cost cost= new Cost(source, target);
cost.rank= Cost.IDENTITY_RANK;
if (cost.source == null || cost.target == null) { if (lvalue_to_rvalue(cost))
return cost; return cost;
}
if (cost.source.isSameType(cost.target) || if (promotion(cost))
// 7.3.3.13 for overload resolution the implicit this pointer is treated as return cost;
// if it were a pointer to the derived class
(isImplicitThis && cost.source instanceof ICPPClassType && cost.target instanceof ICPPClassType)) { if (conversion(cost, isImplicitThis))
cost.rank = Cost.IDENTITY_RANK;
return cost; return cost;
}
qualificationConversion(cost); if (qualificationConversion(cost))
return cost;
// If we can't convert the qualifications, then we can't do anything // If we can't convert the qualifications, then we can't do anything
if (cost.qualification == Cost.NO_MATCH_RANK) { cost.rank= Cost.NO_MATCH_RANK;
return cost; return cost;
}
// Was the qualification conversion enough? // if (cost.rank == -1) {
IType s = getUltimateType(cost.source, true); // relaxTemplateParameters(cost);
IType t = getUltimateType(cost.target, true); // }
if (s == null || t == null) {
cost.rank = Cost.NO_MATCH_RANK;
return cost;
}
if (s.isSameType(t) ||
// 7.3.3.13 for overload resolution the implicit this pointer is treated as if
// it were a pointer to the derived class
(isImplicitThis && s instanceof ICPPClassType && t instanceof ICPPClassType)) {
return cost;
}
promotion(cost);
if (cost.promotion > 0 || cost.rank > -1) {
return cost;
}
conversion(cost);
if (cost.rank > -1)
return cost;
derivedToBaseConversion(cost);
if (cost.rank == -1) {
relaxTemplateParameters(cost);
}
return cost;
} }
/** /**
@ -490,64 +457,107 @@ public class Conversions {
} }
/** /**
* Attempts the conversions below and returns whether this completely converts the source to
* the target type.
* [4.1] Lvalue-to-rvalue conversion * [4.1] Lvalue-to-rvalue conversion
* [4.2] array-to-ptr * [4.2] array-to-ptr
* [4.3] function-to-ptr * [4.3] function-to-ptr
*
* @param source
* @param target
* @return
* @throws DOMException
*/ */
private static final Cost lvalue_to_rvalue(IType source, IType target) throws DOMException { private static final boolean lvalue_to_rvalue(final Cost cost) throws DOMException {
Cost cost = new Cost(source, target); // target should not be a reference here.
boolean isConverted= false;
if (!isCompleteType(source)) { IType target = getNestedType(cost.target, REFERENCES | TYPEDEFS);
cost.rank= Cost.NO_MATCH_RANK; IType source= getNestedType(cost.source, TYPEDEFS);
return cost;
}
// 4.1 lvalue to rvalue
IType srcRValue= getNestedType(source, REFERENCES | TYPEDEFS);
if (source instanceof ICPPReferenceType) { if (source instanceof ICPPReferenceType) {
source= ((ICPPReferenceType) source).getType(); // 4.1 lvalue of non-function and non-array
while (source instanceof ITypedef) if (!(srcRValue instanceof IFunctionType) && !(srcRValue instanceof IArrayType)) {
source = ((ITypedef) source).getType(); // 4.1 if T is a non-class type, the type of the rvalue is the cv-unqualified version of T
IType unqualifiedSrcRValue= getNestedType(srcRValue, QUALIFIERS | PTR_QUALIFIERS | TYPEDEFS | REFERENCES);
if (unqualifiedSrcRValue instanceof ICPPClassType) {
if (isCompleteType(unqualifiedSrcRValue)) {
source= srcRValue;
} else {
// ill-formed
cost.rank= Cost.NO_MATCH_RANK;
return true;
}
} else {
source= unqualifiedSrcRValue;
}
cost.rank= Cost.LVALUE_OR_QUALIFICATION_RANK;
isConverted= true;
}
} }
if (target instanceof ICPPReferenceType) {
target= ((ICPPReferenceType) target).getType(); // 4.2 array to pointer conversion
cost.targetHadReference = true; if (!isConverted && srcRValue instanceof IArrayType) {
final IArrayType arrayType= (IArrayType) srcRValue;
if (target instanceof IPointerType) {
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TYPEDEFS);
// 4.2-2 a string literal can be converted to pointer to char
if (!(targetPtrTgt instanceof IQualifierType) || !((IQualifierType) targetPtrTgt).isConst()) {
IType tmp= arrayType.getType();
if (tmp instanceof IQualifierType && ((IQualifierType) tmp).isConst()) {
tmp= ((IQualifierType) tmp).getType();
if (tmp instanceof CPPBasicType) {
IASTExpression val = ((CPPBasicType) tmp).getCreatedFromExpression();
if (val instanceof IASTLiteralExpression) {
IASTLiteralExpression lit= (IASTLiteralExpression) val;
if (lit.getKind() == IASTLiteralExpression.lk_string_literal) {
source= new CPPPointerType(tmp, false, false);
cost.qualification= Cost.CONVERSION_RANK;
cost.rank= Cost.LVALUE_OR_QUALIFICATION_RANK;
isConverted= true;
}
}
}
}
}
}
if (!isConverted && (target instanceof IPointerType || target instanceof IBasicType)) {
source = new CPPPointerType(getNestedType(arrayType.getType(), TYPEDEFS));
cost.rank= Cost.LVALUE_OR_QUALIFICATION_RANK;
isConverted= true;
}
} }
// 4.3 function to pointer conversion // 4.3 function to pointer conversion
if (target instanceof IPointerType && ((IPointerType) target).getType() instanceof IFunctionType && if (!isConverted && target instanceof IPointerType) {
source instanceof IFunctionType) { final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TYPEDEFS);
source = new CPPPointerType(source); if (targetPtrTgt instanceof IFunctionType && srcRValue instanceof IFunctionType) {
} else if (target instanceof IPointerType && source instanceof IArrayType) { source = new CPPPointerType(source);
// 4.2 Array-To-Pointer conversion cost.rank= Cost.LVALUE_OR_QUALIFICATION_RANK;
source = new CPPPointerType(((IArrayType) source).getType()); isConverted= true;
}
} }
// 4.1 if T is a non-class type, the type of the rvalue is the cv-unqualified version of T // this should actually be done in 'checkImplicitConversionSequence', see 13.3.3.1-6 and 8.5.14
if (source instanceof IQualifierType) { // 8.5.14 cv-qualifiers can be ignored for non-class types
IType t = ((IQualifierType) source).getType(); IType unqualifiedTarget= getNestedType(target, QUALIFIERS | PTR_QUALIFIERS | TYPEDEFS | REFERENCES);
while (t instanceof ITypedef) if (!(unqualifiedTarget instanceof ICPPClassType)) {
t = ((ITypedef) t).getType(); IType unqualifiedSource= getNestedType(source, QUALIFIERS | PTR_QUALIFIERS | TYPEDEFS | REFERENCES);
if (!(t instanceof ICPPClassType)) { if (!(unqualifiedSource instanceof ICPPClassType)) {
source = t; source= unqualifiedSource;
target= unqualifiedTarget;
} }
} else if (source instanceof IPointerType && }
(((IPointerType) source).isConst() || ((IPointerType) source).isVolatile())) {
IType t= ((IPointerType) source).getType();
while (t instanceof ITypedef)
t= ((ITypedef) t).getType();
if (!(t instanceof ICPPClassType)) {
source= new CPPPointerType(t);
}
}
cost.source = source; if (source == null || target == null) {
cost.target = target; cost.rank= Cost.NO_MATCH_RANK;
return true;
return cost; }
cost.source= source;
cost.target= target;
if (source.isSameType(target))
return true;
return false;
} }
/** /**
@ -555,136 +565,63 @@ public class Conversions {
* @param cost * @param cost
* @throws DOMException * @throws DOMException
*/ */
private static final void qualificationConversion(Cost cost) throws DOMException{ private static final boolean qualificationConversion(Cost cost) throws DOMException{
boolean canConvert = true;
int requiredConversion = Cost.IDENTITY_RANK;
IType s = cost.source; IType s = cost.source;
IType t = cost.target; IType t = cost.target;
boolean constInEveryCV2k = true; boolean constInEveryCV2k = true;
boolean firstPointer= true; boolean firstPointer= true;
boolean bothArePointers = false;
boolean pointerNonPointerMismatch = false;
while (true) { while (true) {
s= getUltimateTypeViaTypedefs(s); s= getNestedType(s, TYPEDEFS | REFERENCES);
t= getUltimateTypeViaTypedefs(t); t= getNestedType(t, TYPEDEFS | REFERENCES);
final boolean sourceIsPointer= s instanceof IPointerType; if (s instanceof IPointerType && t instanceof IPointerType) {
final boolean targetIsPointer= t instanceof IPointerType; final int cmp= compareQualifications(t, s); // is t more qualified than s?
if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
if (!targetIsPointer) { return false;
if (!sourceIsPointer && !(s instanceof IArrayType)) { } else {
break; final boolean sIsPtrToMember = s instanceof ICPPPointerToMemberType;
} final boolean tIsPtrToMember = t instanceof ICPPPointerToMemberType;
if (t instanceof ICPPBasicType) { if (sIsPtrToMember != tIsPtrToMember) {
if (((ICPPBasicType) t).getType() == ICPPBasicType.t_bool) { return false;
canConvert= true; } else if (sIsPtrToMember) {
requiredConversion = Cost.CONVERSION_RANK; final IType sMemberOf = ((ICPPPointerToMemberType) s).getMemberOfClass();
break; final IType tMemberOf = ((ICPPPointerToMemberType) t).getMemberOfClass();
if (sMemberOf == null || tMemberOf == null || !sMemberOf.isSameType(tMemberOf)) {
return false;
}
} }
} }
if (!bothArePointers) {
pointerNonPointerMismatch = true;
}
canConvert = false;
break;
} else if (!sourceIsPointer) {
canConvert = false;
break;
} else if (s instanceof ICPPPointerToMemberType ^ t instanceof ICPPPointerToMemberType) {
canConvert = false;
break;
}
// Both are pointers
bothArePointers = true;
IPointerType op1= (IPointerType) s;
IPointerType op2= (IPointerType) t;
// If const is in cv1,j then const is in cv2,j. Similarly for volatile if (cmp != 0) {
if ((op1.isConst() && !op2.isConst()) || (op1.isVolatile() && !op2.isVolatile())) { cost.qualification= Cost.CONVERSION_RANK;
canConvert = false;
requiredConversion = Cost.NO_MATCH_RANK;
break;
}
// If cv1,j and cv2,j are different then const is in every cv2,k for 0<k<j
if (!constInEveryCV2k && (op1.isConst() != op2.isConst() ||
op1.isVolatile() != op2.isVolatile())) {
canConvert = false;
requiredConversion = Cost.NO_MATCH_RANK;
break;
}
constInEveryCV2k &= (firstPointer || op2.isConst());
s = op1.getType();
t = op2.getType();
firstPointer= false;
}
if (cost.targetHadReference && s instanceof ICPPReferenceType) {
s = ((ICPPReferenceType) s).getType();
}
if (s instanceof IQualifierType ^ t instanceof IQualifierType) {
if (t instanceof IQualifierType) {
if (!constInEveryCV2k) {
canConvert= false;
requiredConversion= Cost.NO_MATCH_RANK;
} else {
canConvert = true;
requiredConversion = Cost.CONVERSION_RANK;
} }
final IPointerType tPtr = (IPointerType) t;
final IPointerType sPtr = (IPointerType) s;
constInEveryCV2k &= (firstPointer || tPtr.isConst());
s= sPtr.getType();
t= tPtr.getType();
firstPointer= false;
} else { } else {
// 4.2-2 a string literal can be converted to pointer to char break;
if (t instanceof IBasicType && ((IBasicType) t).getType() == IBasicType.t_char &&
s instanceof IQualifierType) {
IType qt = ((IQualifierType) s).getType();
if (qt instanceof CPPBasicType) {
IASTExpression val = ((CPPBasicType) qt).getCreatedFromExpression();
canConvert = (val != null &&
val instanceof IASTLiteralExpression &&
((IASTLiteralExpression) val).getKind() == IASTLiteralExpression.lk_string_literal);
} else {
canConvert = false;
requiredConversion = Cost.NO_MATCH_RANK;
}
} else {
canConvert = false;
requiredConversion = Cost.NO_MATCH_RANK;
}
}
} else if (s instanceof IQualifierType && t instanceof IQualifierType) {
IQualifierType qs = (IQualifierType) s;
IQualifierType qt = (IQualifierType) t;
if (qs.isConst() == qt.isConst() && qs.isVolatile() == qt.isVolatile()) {
requiredConversion = Cost.IDENTITY_RANK;
} else if ((qs.isConst() && !qt.isConst()) || (qs.isVolatile() && !qt.isVolatile()) || !constInEveryCV2k) {
requiredConversion = Cost.NO_MATCH_RANK;
canConvert= false;
} else {
requiredConversion = Cost.CONVERSION_RANK;
}
} else if (!pointerNonPointerMismatch && constInEveryCV2k && !canConvert) {
canConvert = true;
requiredConversion = Cost.CONVERSION_RANK;
while (s instanceof ITypeContainer) {
if (s instanceof IQualifierType) {
canConvert = false;
} else if (s instanceof IPointerType) {
canConvert = !((IPointerType) s).isConst() && !((IPointerType) s).isVolatile();
}
if (!canConvert) {
requiredConversion = Cost.NO_MATCH_RANK;
break;
}
s = ((ITypeContainer) s).getType();
} }
} }
cost.qualification = requiredConversion; if (s instanceof IQualifierType || t instanceof IQualifierType) {
if (canConvert) { int cmp= compareQualifications(t, s); // is t more qualified than s?
cost.rank = Cost.LVALUE_OR_QUALIFICATION_RANK; if (cmp == -1 || (cmp == 1 && !constInEveryCV2k)) {
} return false;
} else if (cmp != 0) {
cost.qualification= Cost.CONVERSION_RANK;
}
s= getNestedType(s, QUALIFIERS | TYPEDEFS | REFERENCES);
t= getNestedType(t, QUALIFIERS | TYPEDEFS | REFERENCES);
}
return s != null && t != null && s.isSameType(t);
} }
/** /**
* Attempts promotions and returns whether the promotion converted the type.
*
* [4.5] [4.6] Promotion * [4.5] [4.6] Promotion
* *
* 4.5-1 char, signed char, unsigned char, short int or unsigned short int * 4.5-1 char, signed char, unsigned char, short int or unsigned short int
@ -696,136 +633,168 @@ public class Conversions {
* 4.6 float can be promoted to double * 4.6 float can be promoted to double
* @throws DOMException * @throws DOMException
*/ */
private static final void promotion(Cost cost) throws DOMException{ private static final boolean promotion(Cost cost) throws DOMException{
IType src = cost.source; IType src = cost.source;
IType trg = cost.target; IType trg = cost.target;
if (src.isSameType(trg)) boolean canPromote= false;
return; if (trg instanceof IBasicType) {
IBasicType basicTgt = (IBasicType) trg;
final int tType = basicTgt.getType();
if (src instanceof IBasicType && trg instanceof IBasicType) { if (src instanceof IBasicType) {
int sType = ((IBasicType) src).getType(); final IBasicType basicSrc = (IBasicType) src;
int tType = ((IBasicType) trg).getType(); int sType = basicSrc.getType();
if ((tType == IBasicType.t_int && (sType == IBasicType.t_int || // short, long, unsigned etc if (tType == IBasicType.t_int) {
sType == IBasicType.t_char || switch (sType) {
sType == ICPPBasicType.t_bool || case IBasicType.t_int: // short, and unsigned short
sType == ICPPBasicType.t_wchar_t || if (basicSrc.isShort()) {
sType == IBasicType.t_unspecified)) || // treat unspecified as int canPromote= true;
(tType == IBasicType.t_double && sType == IBasicType.t_float)) { }
cost.promotion = 1; break;
case IBasicType.t_char:
case ICPPBasicType.t_bool:
case ICPPBasicType.t_wchar_t:
case IBasicType.t_unspecified: // treat unspecified as int
canPromote= true;
break;
}
} else if (tType == IBasicType.t_double && sType == IBasicType.t_float) {
canPromote= true;
}
} else if (src instanceof IEnumeration) {
if (tType == IBasicType.t_int || tType == IBasicType.t_unspecified) {
canPromote= true;
}
} }
} else if (src instanceof IEnumeration && trg instanceof IBasicType &&
(((IBasicType) trg).getType() == IBasicType.t_int ||
((IBasicType) trg).getType() == IBasicType.t_unspecified)) {
cost.promotion = 1;
} }
if (canPromote) {
cost.rank = (cost.promotion > 0) ? Cost.PROMOTION_RANK : Cost.NO_MATCH_RANK; cost.promotion = 1;
cost.rank= Cost.PROMOTION_RANK;
return true;
}
return false;
} }
/** /**
* Attempts conversions and returns whether the conversion succeeded.
* [4.7] Integral conversions * [4.7] Integral conversions
* [4.8] Floating point conversions * [4.8] Floating point conversions
* [4.9] Floating-integral conversions * [4.9] Floating-integral conversions
* [4.10] Pointer conversions * [4.10] Pointer conversions
* [4.11] Pointer to member conversions * [4.11] Pointer to member conversions
* @param cost
* @throws DOMException
*/ */
private static final void conversion(Cost cost) throws DOMException{ private static final boolean conversion(Cost cost, boolean forImplicitThis) throws DOMException{
final IType src = cost.source; final IType s = cost.source;
final IType trg = cost.target; final IType t = cost.target;
cost.conversion = 0; cost.conversion = 0;
cost.detail = 0; cost.detail = 0;
IType[] sHolder= new IType[1], tHolder= new IType[1]; if (t instanceof IBasicType) {
IType s = getUltimateType(src, sHolder, true); // 4.7 integral conversion
IType t = getUltimateType(trg, tHolder, true); // 4.8 floating point conversion
IType sPrev= sHolder[0], tPrev= tHolder[0]; // 4.9 floating-integral conversion
if (s instanceof IBasicType || s instanceof IEnumeration) {
if (src instanceof CPPBasicType && trg instanceof IPointerType) { // 4.7 An rvalue of an integer type can be converted to an rvalue of another integer type.
// 4.10-1 an integral constant expression of integer type that evaluates to 0 can // An rvalue of an enumeration type can be converted to an rvalue of an integer type.
// be converted to a pointer type cost.rank = Cost.CONVERSION_RANK;
IASTExpression exp = ((CPPBasicType) src).getCreatedFromExpression(); cost.conversion = 1;
if (exp != null) { return true;
Long val= Value.create(exp, Value.MAX_RECURSION_DEPTH).numericalValue(); }
if (val != null && val == 0) { // 4.12 pointer or pointer to member type can be converted to an rvalue of type bool
cost.rank = Cost.CONVERSION_RANK; final int tgtType = ((IBasicType) t).getType();
cost.conversion = 1; if (tgtType == ICPPBasicType.t_bool && s instanceof IPointerType) {
}
}
} else if (sPrev instanceof IPointerType) {
// 4.10-2 an rvalue of type "pointer to cv T", where T is an object type can be
// converted to an rvalue of type "pointer to cv void"
if (tPrev instanceof IPointerType && t instanceof IBasicType &&
((IBasicType) t).getType() == IBasicType.t_void) {
cost.rank = Cost.CONVERSION_RANK; cost.rank = Cost.CONVERSION_RANK;
cost.conversion = 1; cost.conversion = 1;
cost.detail = 2; return true;
return; }
}
if (t instanceof IPointerType) {
IPointerType tgtPtr= (IPointerType) t;
if (s instanceof CPPBasicType) {
// 4.10-1 an integral constant expression of integer type that evaluates to 0 can
// be converted to a pointer type
// 4.11-1 same for pointer to member
IASTExpression exp = ((CPPBasicType) s).getCreatedFromExpression();
if (exp != null) {
Long val= Value.create(exp, Value.MAX_RECURSION_DEPTH).numericalValue();
if (val != null && val == 0) {
cost.rank = Cost.CONVERSION_RANK;
cost.conversion = 1;
return true;
}
}
return false;
} }
// 4.10-3 An rvalue of type "pointer to cv D", where D is a class type can be converted if (s instanceof IPointerType) {
// to an rvalue of type "pointer to cv B", where B is a base class of D. IPointerType srcPtr= (IPointerType) s;
else if (s instanceof ICPPClassType && tPrev instanceof IPointerType && t instanceof ICPPClassType) { // 4.10-2 an rvalue of type "pointer to cv T", where T is an object type can be
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, s, t); // converted to an rvalue of type "pointer to cv void"
cost.rank= (depth > -1) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK; IType tgtPtrTgt= getNestedType(tgtPtr.getType(), TYPEDEFS | QUALIFIERS | REFERENCES);
cost.conversion= (depth > -1) ? depth : 0; if (tgtPtrTgt instanceof IBasicType && ((IBasicType) tgtPtrTgt).getType() == IBasicType.t_void) {
cost.detail= 1; cost.rank = Cost.CONVERSION_RANK;
return; cost.conversion = 1;
} cost.detail = 2;
// 4.12 if the target is a bool, we can still convert int cv= getCVQualifier(srcPtr.getType());
else if (!(trg instanceof IBasicType && ((IBasicType) trg).getType() == ICPPBasicType.t_bool)) { cost.source= new CPPPointerType(addQualifiers(CPPSemantics.VOID_TYPE, (cv&1) != 0, (cv&2) != 0));
return; return false;
} }
}
final boolean tIsPtrToMember = t instanceof ICPPPointerToMemberType;
if (t instanceof IBasicType && (s instanceof IBasicType || s instanceof IEnumeration)) { final boolean sIsPtrToMember = s instanceof ICPPPointerToMemberType;
// 4.7 An rvalue of an integer type can be converted to an rvalue of another integer type. if (!tIsPtrToMember && !sIsPtrToMember) {
// An rvalue of an enumeration type can be converted to an rvalue of an integer type. // 4.10-3 An rvalue of type "pointer to cv D", where D is a class type can be converted
cost.rank = Cost.CONVERSION_RANK; // to an rvalue of type "pointer to cv B", where B is a base class of D.
cost.conversion = 1; IType srcPtrTgt= getNestedType(srcPtr.getType(), TYPEDEFS | QUALIFIERS | REFERENCES);
} else if (trg instanceof IBasicType && ((IBasicType) trg).getType() == ICPPBasicType.t_bool && if (tgtPtrTgt instanceof ICPPClassType && srcPtrTgt instanceof ICPPClassType) {
s instanceof IPointerType) { int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, srcPtrTgt, tgtPtrTgt);
// 4.12 pointer or pointer to member type can be converted to an rvalue of type bool if (depth == -1) {
cost.rank = Cost.CONVERSION_RANK; cost.rank= Cost.NO_MATCH_RANK;
cost.conversion = 1; return true;
} else if (s instanceof ICPPPointerToMemberType && t instanceof ICPPPointerToMemberType) { }
// 4.11-2 An rvalue of type "pointer to member of B of type cv T", where B is a class type, if (depth > 0) {
// can be converted to an rvalue of type "pointer to member of D of type cv T" where D is a if (!forImplicitThis) {
// derived class of B cost.rank= Cost.CONVERSION_RANK;
ICPPPointerToMemberType spm = (ICPPPointerToMemberType) s; cost.conversion= depth;
ICPPPointerToMemberType tpm = (ICPPPointerToMemberType) t; }
IType st = spm.getType(); cost.detail= 1;
IType tt = tpm.getType(); int cv= getCVQualifier(srcPtr.getType());
if (st != null && tt != null && st.isSameType(tt)) { cost.source= new CPPPointerType(addQualifiers(tgtPtrTgt, (cv&1) != 0, (cv&2) != 0));
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, }
tpm.getMemberOfClass(), spm.getMemberOfClass()); return false;
cost.rank= (depth > -1) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK; }
cost.conversion= (depth > -1) ? depth : 0; } else if (tIsPtrToMember && sIsPtrToMember) {
cost.detail= 1; // 4.11-2 An rvalue of type "pointer to member of B of type cv T", where B is a class type,
// can be converted to an rvalue of type "pointer to member of D of type cv T" where D is a
// derived class of B
ICPPPointerToMemberType spm = (ICPPPointerToMemberType) s;
ICPPPointerToMemberType tpm = (ICPPPointerToMemberType) t;
IType st = spm.getType();
IType tt = tpm.getType();
if (st != null && tt != null && st.isSameType(tt)) {
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH,
tpm.getMemberOfClass(), spm.getMemberOfClass());
if (depth == -1) {
cost.rank= Cost.NO_MATCH_RANK;
return true;
}
if (depth > 0) {
cost.rank= Cost.CONVERSION_RANK;
cost.conversion= depth;
cost.detail= 1;
cost.source = new CPPPointerToMemberType(spm.getType(),
tpm.getMemberOfClass(), spm.isConst(), spm.isVolatile());
}
return false;
}
}
} }
} }
return false;
} }
/**
* [13.3.3.1-6] Derived to base conversion
* @param cost
* @throws DOMException
*/
private static final void derivedToBaseConversion(Cost cost) throws DOMException {
IType s = getUltimateType(cost.source, true);
IType t = getUltimateType(cost.target, true);
if (cost.targetHadReference && s instanceof ICPPClassType && t instanceof ICPPClassType) {
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, s, t);
if (depth > -1) {
cost.rank = Cost.DERIVED_TO_BASE_CONVERSION;
cost.conversion = depth;
}
}
}
/** /**
* @param type * @param type
* @return whether the specified type has an associated definition * @return whether the specified type has an associated definition
@ -850,17 +819,22 @@ public class Conversions {
return true; return true;
} }
/** // mstodo must be part of implicit conversion
* Allows any very loose matching between template parameters. // /**
* @param cost // * [13.3.3.1-6] Derived to base conversion
*/ // * @param cost
private static final void relaxTemplateParameters(Cost cost) { // * @throws DOMException
IType s = getUltimateType(cost.source, false); // */
IType t = getUltimateType(cost.target, false); // private static final void derivedToBaseConversion(Cost cost) throws DOMException {
// IType s = getUltimateType(cost.source, true);
if ((s instanceof ICPPTemplateTypeParameter && t instanceof ICPPTemplateTypeParameter) || // IType t = getUltimateType(cost.target, true);
(s instanceof ICPPTemplateTemplateParameter && t instanceof ICPPTemplateTemplateParameter)) { //
cost.rank = Cost.FUZZY_TEMPLATE_PARAMETERS; // if (s instanceof ICPPClassType && t instanceof ICPPClassType) {
} // int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, s, t);
} // if (depth > -1) {
// cost.rank = Cost.DERIVED_TO_BASE_CONVERSION;
// cost.conversion = depth;
// }
// }
// }
} }

View file

@ -42,8 +42,6 @@ class Cost {
public IType source; public IType source;
public IType target; public IType target;
public boolean targetHadReference = false;
public int lvalue; public int lvalue;
public int promotion; public int promotion;
public int conversion; public int conversion;
@ -108,11 +106,7 @@ class Cost {
op2 = null; op2 = null;
while (true) { while (true) {
if (t1 instanceof ITypedef) { if (t1 instanceof ITypedef) {
try { t1 = ((ITypedef) t1).getType();
t1 = ((ITypedef) t1).getType();
} catch (DOMException e) {
t1 = e.getProblem();
}
} else { } else {
if (t1 instanceof IPointerType) if (t1 instanceof IPointerType)
op1 = (IPointerType) t1; op1 = (IPointerType) t1;
@ -121,11 +115,7 @@ class Cost {
} }
while (true) { while (true) {
if (t2 instanceof ITypedef) { if (t2 instanceof ITypedef) {
try { t2 = ((ITypedef) t2).getType();
t2 = ((ITypedef) t2).getType();
} catch (DOMException e) {
t2 = e.getProblem();
}
} else { } else {
if (t2 instanceof IPointerType) if (t2 instanceof IPointerType)
op2 = (IPointerType) t2; op2 = (IPointerType) t2;

View file

@ -37,6 +37,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectSet; import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument;
@ -53,6 +54,8 @@ public class SemanticUtil {
static final int TYPEDEFS = 0x1; static final int TYPEDEFS = 0x1;
static final int REFERENCES = 0x2; static final int REFERENCES = 0x2;
static final int QUALIFIERS = 0x4;
static final int PTR_QUALIFIERS= 0x8;
static { static {
final int OPERATOR_SPC= OPERATOR_CHARS.length + 1; final int OPERATOR_SPC= OPERATOR_CHARS.length + 1;
@ -161,50 +164,32 @@ public class SemanticUtil {
* @return the deepest type in a type container sequence * @return the deepest type in a type container sequence
*/ */
public static IType getUltimateType(IType type, boolean stopAtPointerToMember) { public static IType getUltimateType(IType type, boolean stopAtPointerToMember) {
return getUltimateType(type, null, stopAtPointerToMember); try {
while (true) {
if (type instanceof ITypedef) {
IType tt= ((ITypedef) type).getType();
if (tt == null)
return type;
type= tt;
} else if (type instanceof IQualifierType) {
type= ((IQualifierType) type).getType();
} else if (stopAtPointerToMember && type instanceof ICPPPointerToMemberType) {
return type;
} else if (type instanceof IPointerType) {
type= ((IPointerType) type).getType();
} else if (type instanceof IArrayType) {
type= ((IArrayType) type).getType();
} else if (type instanceof ICPPReferenceType) {
type= ((ICPPReferenceType) type).getType();
} else {
return type;
}
}
} catch (DOMException e) {
return e.getProblem();
}
} }
/**
* Descends into type containers, stopping at pointer-to-member types if specified.
* @param type the root type
* @param lastPointerType if non-null, the deepest pointer or array type encountered
* is stored in element zero.
* @param stopAtPointerToMember if true, do not descend into ICPPPointerToMember types
* @return the deepest type in a type container sequence
*/
static IType getUltimateType(IType type, IType[] lastPointerType, boolean stopAtPointerToMember) {
try {
while (true) {
if (type instanceof ITypedef) {
IType tt= ((ITypedef) type).getType();
if (tt == null)
return type;
type= tt;
} else if (type instanceof IQualifierType) {
type= ((IQualifierType) type).getType();
} else if (stopAtPointerToMember && type instanceof ICPPPointerToMemberType) {
return type;
} else if (type instanceof IPointerType) {
if (lastPointerType != null) {
lastPointerType[0]= type;
}
type= ((IPointerType) type).getType();
} else if (type instanceof IArrayType) {
if (lastPointerType != null) {
lastPointerType[0]= type;
}
type= ((IArrayType) type).getType();
} else if (type instanceof ICPPReferenceType) {
type= ((ICPPReferenceType) type).getType();
} else {
return type;
}
}
} catch (DOMException e) {
return e.getProblem();
}
}
/** /**
* Descends into type containers, stopping at pointer or * Descends into type containers, stopping at pointer or
* pointer-to-member types. * pointer-to-member types.
@ -245,6 +230,8 @@ public class SemanticUtil {
public static IType getNestedType(IType type, int options) { public static IType getNestedType(IType type, int options) {
boolean typedefs= (options & TYPEDEFS) != 0; boolean typedefs= (options & TYPEDEFS) != 0;
boolean refs= (options & REFERENCES) != 0; boolean refs= (options & REFERENCES) != 0;
boolean qualifiers= (options & QUALIFIERS) != 0;
boolean ptrQualifiers= (options & PTR_QUALIFIERS) != 0;
try { try {
while (true) { while (true) {
IType t= null; IType t= null;
@ -252,6 +239,22 @@ public class SemanticUtil {
t= ((ITypedef) type).getType(); t= ((ITypedef) type).getType();
} else if (refs && type instanceof ICPPReferenceType) { } else if (refs && type instanceof ICPPReferenceType) {
t= ((ICPPReferenceType) type).getType(); t= ((ICPPReferenceType) type).getType();
} else if (qualifiers && type instanceof IQualifierType) {
t= ((IQualifierType) type).getType();
} else if (ptrQualifiers && type instanceof IPointerType) {
if (type instanceof CPPPointerType) {
return ((CPPPointerType) type).stripQualifiers();
}
IPointerType ptr= (IPointerType) type;
if (ptr.isConst() || ptr.isVolatile()) {
if (ptr instanceof ICPPPointerToMemberType) {
final IType memberOfClass = ((ICPPPointerToMemberType) ptr).getMemberOfClass();
if (memberOfClass instanceof ICPPClassType)
return new CPPPointerToMemberType(ptr.getType(), memberOfClass, false, false);
} else {
return new CPPPointerType(ptr.getType(), false, false);
}
}
} }
if (t == null) if (t == null)
return type; return type;
@ -378,36 +381,58 @@ public class SemanticUtil {
* Adjusts the parameter type according to 8.3.5-3: * Adjusts the parameter type according to 8.3.5-3:
* cv-qualifiers are deleted, arrays and function types are converted to pointers. * cv-qualifiers are deleted, arrays and function types are converted to pointers.
*/ */
public static IType adjustParameterType(IType pt) { public static IType adjustParameterType(final IType pt, boolean forFunctionType) {
// bug 239975 // bug 239975
IType noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt); IType t= SemanticUtil.getUltimateTypeViaTypedefs(pt);
try {
if (t instanceof IArrayType) {
IArrayType at = (IArrayType) t;
return new CPPPointerType(at.getType());
}
} catch (DOMException e) {
return e.getProblem();
}
if (t instanceof IFunctionType) {
return new CPPPointerType(pt);
}
//8.3.5-3 //8.3.5-3
//Any cv-qualifier modifying a parameter type is deleted. //Any cv-qualifier modifying a parameter type is deleted.
//so only create the base type from the declspec and not the qualifiers if (forFunctionType && (t instanceof IQualifierType || t instanceof IPointerType)) {
try { return SemanticUtil.getNestedType(t, TYPEDEFS | QUALIFIERS | PTR_QUALIFIERS);
if (noTypedef instanceof IQualifierType) {
pt= ((IQualifierType) noTypedef).getType();
noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
}
if (noTypedef instanceof CPPPointerType) {
pt= ((CPPPointerType) noTypedef).stripQualifiers();
noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
}
//any parameter of type array of T is adjusted to be pointer to T
if (noTypedef instanceof IArrayType) {
IArrayType at = (IArrayType) noTypedef;
pt = new CPPPointerType(at.getType());
noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
}
} catch (DOMException e) {
pt = e.getProblem();
}
//any parameter to type function returning T is adjusted to be pointer to function
if (noTypedef instanceof IFunctionType) {
pt = new CPPPointerType(pt);
} }
return pt; return pt;
} }
public static IType addQualifiers(IType baseType, boolean cnst, boolean vol) {
if (cnst || vol) {
try {
if (baseType instanceof IQualifierType) {
IQualifierType qt= (IQualifierType) baseType;
if ((cnst && !qt.isConst()) || (vol && !qt.isVolatile())) {
return new CPPQualifierType(qt.getType(), cnst || qt.isConst(), vol || qt.isVolatile());
}
return baseType;
} else if (baseType instanceof ICPPPointerToMemberType) {
ICPPPointerToMemberType pt= (ICPPPointerToMemberType) baseType;
if ((cnst && !pt.isConst()) || (vol && !pt.isVolatile())) {
return new CPPPointerToMemberType(pt.getType(), pt.getMemberOfClass(), cnst
|| pt.isConst(), vol || pt.isVolatile());
}
return baseType;
} else if (baseType instanceof IPointerType) {
IPointerType pt= (IPointerType) baseType;
if ((cnst && !pt.isConst()) || (vol && !pt.isVolatile())) {
return new CPPPointerType(pt.getType(), cnst || pt.isConst(), vol || pt.isVolatile());
}
return baseType;
}
} catch (DOMException e) {
}
return new CPPQualifierType(baseType, cnst, vol);
}
return baseType;
}
} }