mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 01:15:29 +02:00
Rework of standard conversion sequence, bug 263159.
This commit is contained in:
parent
02ecde30f4
commit
7e4bb073a8
12 changed files with 491 additions and 503 deletions
|
@ -5941,7 +5941,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// f3(r);
|
||||
// f4(s);
|
||||
// }
|
||||
public void _testArrayToPointerConversion() throws Exception {
|
||||
public void testArrayToPointerConversion() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
ba.assertNonProblem("f1(p)", 2, ICPPFunction.class);
|
||||
ba.assertProblem("f2(q)", 2);
|
||||
|
@ -6619,7 +6619,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// void test() {
|
||||
// f(a());
|
||||
// }
|
||||
public void _testBug263152_1() throws Exception {
|
||||
public void testBug263152_1() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
ba.assertProblem("f(a())", 1);
|
||||
}
|
||||
|
@ -6635,7 +6635,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// void test(B p) {
|
||||
// p.m(a());
|
||||
// }
|
||||
public void _testBug263152_2() throws Exception {
|
||||
public void testBug263152_2() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
ba.assertNonProblem("m(a())", 1, ICPPMethod.class);
|
||||
}
|
||||
|
@ -6699,7 +6699,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// fip(0);
|
||||
// fia(0);
|
||||
// }
|
||||
public void _testNonPointerToPointerConversion_263707() throws Exception {
|
||||
public void testNonPointerToPointerConversion_263707() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
ba.assertProblem("fip(1)", 3);
|
||||
ba.assertProblem("fia(1)", 3);
|
||||
|
|
|
@ -228,21 +228,25 @@ public class ASTTypeUtil {
|
|||
}
|
||||
result.append(Keywords.cpRBRACKET);
|
||||
} else if (type instanceof IBasicType) {
|
||||
IBasicType basicType= (IBasicType) type;
|
||||
try {
|
||||
if (((IBasicType) type).isSigned()) {
|
||||
result.append(Keywords.SIGNED); needSpace = true;
|
||||
} else if (((IBasicType) type).isUnsigned()) {
|
||||
if (basicType.isSigned()) {
|
||||
// 3.9.1.2: signed integer types
|
||||
if (!normalize || basicType.getType() == IBasicType.t_char) {
|
||||
result.append(Keywords.SIGNED); needSpace = true;
|
||||
}
|
||||
} else if (basicType.isUnsigned()) {
|
||||
if (needSpace) {
|
||||
result.append(SPACE); needSpace = false;
|
||||
}
|
||||
result.append(Keywords.UNSIGNED); needSpace = true;
|
||||
}
|
||||
if (((IBasicType) type).isLong()) {
|
||||
if (basicType.isLong()) {
|
||||
if (needSpace) {
|
||||
result.append(SPACE); needSpace = false;
|
||||
}
|
||||
result.append(Keywords.LONG); needSpace = true;
|
||||
} else if (((IBasicType) type).isShort()) {
|
||||
} else if (basicType.isShort()) {
|
||||
if (needSpace) {
|
||||
result.append(SPACE); needSpace = false;
|
||||
}
|
||||
|
@ -316,7 +320,7 @@ public class ASTTypeUtil {
|
|||
}
|
||||
|
||||
try {
|
||||
switch (((IBasicType) type).getType()) {
|
||||
switch (basicType.getType()) {
|
||||
case IBasicType.t_char:
|
||||
if (needSpace) result.append(SPACE);
|
||||
result.append(Keywords.CHAR);
|
||||
|
|
|
@ -103,7 +103,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
|||
case lk_string_literal:
|
||||
IType type = new CPPBasicType(IBasicType.t_char, 0, this);
|
||||
type = new CPPQualifierType(type, true, false);
|
||||
return new CPPPointerType(type);
|
||||
return new CPPArrayType(type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -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.CPPTemplates;
|
||||
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.
|
||||
|
@ -100,7 +101,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
|||
char[] className = name.getLookupKey();
|
||||
|
||||
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) };
|
||||
|
||||
int i= 0;
|
||||
|
|
|
@ -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.ProblemBinding;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -178,7 +179,8 @@ public class CPPParameter extends PlatformObject implements ICPPParameter, ICPPI
|
|||
*/
|
||||
public IType getType() {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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.cpp.ICPPASTPointerToMember;
|
||||
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.ICPPPointerToMemberType;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexType;
|
||||
|
@ -40,7 +39,7 @@ public class CPPPointerToMemberType extends CPPPointerType implements ICPPPointe
|
|||
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);
|
||||
this.classType = thisType;
|
||||
}
|
||||
|
|
|
@ -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.CPPCompositeBinding;
|
||||
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.CPPScope;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownBinding;
|
||||
|
@ -1974,10 +1973,7 @@ public class CPPSemantics {
|
|||
if (owner instanceof ICPPClassTemplate) {
|
||||
owner= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) owner);
|
||||
}
|
||||
IType implicitType= owner;
|
||||
if (ftype.isConst() || ftype.isVolatile()) {
|
||||
implicitType = new CPPQualifierType(implicitType, ftype.isConst(), ftype.isVolatile());
|
||||
}
|
||||
IType implicitType= SemanticUtil.addQualifiers(owner, ftype.isConst(), ftype.isVolatile());
|
||||
result[0]= new CPPReferenceType(implicitType);
|
||||
return result;
|
||||
}
|
||||
|
@ -2507,9 +2503,7 @@ public class CPPSemantics {
|
|||
private static ICPPVariable createVariable(IASTName name, final IType type, final boolean isConst, final boolean isVolatile) {
|
||||
return new CPPVariable(name) {
|
||||
@Override public IType getType() {
|
||||
if (isConst || isVolatile)
|
||||
return new CPPQualifierType(type, isConst, isVolatile);
|
||||
return type;
|
||||
return SemanticUtil.addQualifiers(type, isConst, isVolatile);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -822,7 +822,7 @@ public class CPPTemplates {
|
|||
IType newMemberOfClass = instantiateType(memberOfClass, tpMap, within);
|
||||
if (newNestedType != nestedType || newMemberOfClass != memberOfClass) {
|
||||
if (newMemberOfClass instanceof ICPPClassType) {
|
||||
return new CPPPointerToMemberType(newNestedType, (ICPPClassType) newMemberOfClass,
|
||||
return new CPPPointerToMemberType(newNestedType, newMemberOfClass,
|
||||
ptm.isConst(), ptm.isVolatile());
|
||||
}
|
||||
return type;
|
||||
|
@ -1407,7 +1407,7 @@ public class CPPTemplates {
|
|||
IType par= instPars[j];
|
||||
if (isDependentType(par)) {
|
||||
// 14.8.2.1
|
||||
par= SemanticUtil.adjustParameterType(par);
|
||||
par= SemanticUtil.adjustParameterType(par, true);
|
||||
if (!deduceTemplateParameterMap(par, fnArgs[j], map)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1532,7 +1532,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
pt = createType(pDeclSpec);
|
||||
pt = createType(pt, pDtor);
|
||||
|
||||
pt = SemanticUtil.adjustParameterType(pt);
|
||||
pt = SemanticUtil.adjustParameterType(pt, true);
|
||||
pTypes[i] = pt;
|
||||
}
|
||||
|
||||
|
@ -1766,8 +1766,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
if (type instanceof ICPPClassTemplate) {
|
||||
type= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) type);
|
||||
}
|
||||
if (dtor.isConst() || dtor.isVolatile())
|
||||
type = new CPPQualifierType(type, dtor.isConst(), dtor.isVolatile());
|
||||
type = SemanticUtil.addQualifiers(type, dtor.isConst(), dtor.isVolatile());
|
||||
type = new CPPPointerType(type);
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -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.IQualifierType;
|
||||
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.ICPPBasicType;
|
||||
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.ICPPReferenceType;
|
||||
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.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.ICPPDeferredClassInstance;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
|
||||
|
@ -78,8 +75,7 @@ public class Conversions {
|
|||
if (source instanceof ICPPReferenceType)
|
||||
source= getNestedType(source, TYPEDEFS | REFERENCES);
|
||||
|
||||
IType T2= source instanceof IQualifierType ?
|
||||
getNestedType(((IQualifierType) source).getType(), TYPEDEFS | REFERENCES) : source;
|
||||
IType T2= getNestedType(source, TYPEDEFS | REFERENCES | QUALIFIERS | PTR_QUALIFIERS);
|
||||
|
||||
// [8.5.3-5] Is an lvalue (but is not a bit-field), and "cv1 T1" is reference-compatible with "cv2 T2,"
|
||||
if (lvalue) {
|
||||
|
@ -150,43 +146,37 @@ public class Conversions {
|
|||
}
|
||||
|
||||
// [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 (cv1T1 instanceof IQualifierType) {
|
||||
cv1isConst= ((IQualifierType) cv1T1).isConst() && !((IQualifierType) cv1T1).isVolatile();
|
||||
} else if (cv1T1 instanceof IPointerType) {
|
||||
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;
|
||||
// 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.
|
||||
IType T1= getNestedType(cv1T1, TYPEDEFS | REFERENCES | QUALIFIERS | PTR_QUALIFIERS);
|
||||
boolean illformed= isReferenceRelated(T1, T2) >= 0 && compareQualifications(cv1T1, source) < 0;
|
||||
|
||||
// We must do a non-reference initialization
|
||||
if (!illformed) {
|
||||
Cost cost= checkStandardConversionSequence(source, cv1T1, isImpliedObject);
|
||||
// 12.3-4 At most one user-defined conversion is implicitly applied to
|
||||
// a single value. (also prevents infinite loop)
|
||||
if (allowUDC && (cost.rank == Cost.NO_MATCH_RANK ||
|
||||
cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) {
|
||||
Cost temp = checkUserDefinedConversionSequence(source, cv1T1);
|
||||
if (temp != null) {
|
||||
cost = temp;
|
||||
}
|
||||
if (!illformed) {
|
||||
Cost cost= checkStandardConversionSequence(source, cv1T1, isImpliedObject);
|
||||
// 12.3-4 At most one user-defined conversion is implicitly applied to
|
||||
// a single value. (also prevents infinite loop)
|
||||
if (allowUDC && (cost.rank == Cost.NO_MATCH_RANK ||
|
||||
cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) {
|
||||
Cost temp = checkUserDefinedConversionSequence(source, cv1T1);
|
||||
if (temp != null) {
|
||||
cost = temp;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
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)
|
||||
* ordering on cv-qualifiers, so that a type can be said to be more
|
||||
* cv-qualified than another.
|
||||
* @param cv1
|
||||
* @param cv2
|
||||
* @return <ul>
|
||||
* <li>GT 1 if cv1 is more qualified than cv2
|
||||
* <li>EQ 0 if cv1 and cv2 are equally qualified
|
||||
|
@ -217,40 +205,48 @@ public class Conversions {
|
|||
* </ul>
|
||||
* @throws DOMException
|
||||
*/
|
||||
private static final int compareQualifications(IType cv1, IType cv2) throws DOMException {
|
||||
boolean cv1Const= false, cv2Const= false, cv1Volatile= false, cv2Volatile= false;
|
||||
if (cv1 instanceof IQualifierType) {
|
||||
IQualifierType qt1= (IQualifierType) cv1;
|
||||
cv1Const= qt1.isConst();
|
||||
cv1Volatile= qt1.isVolatile();
|
||||
} else if (cv1 instanceof IPointerType) {
|
||||
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);
|
||||
private static final int compareQualifications(IType t1, IType t2) throws DOMException {
|
||||
int cv1= getCVQualifier(t1);
|
||||
int cv2= getCVQualifier(t2);
|
||||
|
||||
// same qualifications
|
||||
if (cv1 == cv2)
|
||||
return 0;
|
||||
|
||||
if (cmpConst == cmpVolatile) {
|
||||
return cmpConst;
|
||||
} else if (cmpConst != 0 && cmpVolatile == 0) {
|
||||
return cmpConst;
|
||||
} else if (cmpConst == 0 && cmpVolatile != 0) {
|
||||
return cmpVolatile;
|
||||
// both are different but not comparable
|
||||
final int diffs= cv1 ^ cv2;
|
||||
if (diffs == 3 && cv1 != 3 && cv2 != 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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,
|
||||
* or T1 is a base class of T2.
|
||||
|
@ -264,11 +260,13 @@ public class Conversions {
|
|||
// The way cv-qualification is currently modeled means
|
||||
// we must cope with IPointerType objects separately.
|
||||
if (t instanceof IPointerType && s instanceof IPointerType) {
|
||||
t= ((IPointerType) t).getType();
|
||||
s= ((IPointerType) s).getType();
|
||||
t= SemanticUtil.getNestedType(((IPointerType) t).getType(), TYPEDEFS | REFERENCES);
|
||||
s= SemanticUtil.getNestedType(((IPointerType) s).getType(), TYPEDEFS | REFERENCES);
|
||||
} else {
|
||||
t= t instanceof IQualifierType ? ((IQualifierType) t).getType() : t;
|
||||
s= s instanceof IQualifierType ? ((IQualifierType) s).getType() : s;
|
||||
if (t instanceof IQualifierType)
|
||||
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) {
|
||||
return calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, s, t);
|
||||
|
@ -298,6 +296,7 @@ public class Conversions {
|
|||
Cost cost= new Cost(cv2Source, cv1Target);
|
||||
cost.qualification= cmp > 0 ? Cost.CONVERSION_RANK : Cost.IDENTITY_RANK;
|
||||
cost.conversion= inheritanceDist;
|
||||
cost.rank= Cost.IDENTITY_RANK;
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
@ -311,59 +310,27 @@ public class Conversions {
|
|||
*/
|
||||
protected static final Cost checkStandardConversionSequence(IType source, IType target,
|
||||
boolean isImplicitThis) throws DOMException {
|
||||
Cost cost = lvalue_to_rvalue(source, target);
|
||||
|
||||
if (cost.source == null || cost.target == null) {
|
||||
final Cost cost= new Cost(source, target);
|
||||
cost.rank= Cost.IDENTITY_RANK;
|
||||
if (lvalue_to_rvalue(cost))
|
||||
return cost;
|
||||
}
|
||||
|
||||
if (cost.source.isSameType(cost.target) ||
|
||||
// 7.3.3.13 for overload resolution the implicit this pointer is treated as
|
||||
// if it were a pointer to the derived class
|
||||
(isImplicitThis && cost.source instanceof ICPPClassType && cost.target instanceof ICPPClassType)) {
|
||||
cost.rank = Cost.IDENTITY_RANK;
|
||||
if (promotion(cost))
|
||||
return cost;
|
||||
|
||||
if (conversion(cost, isImplicitThis))
|
||||
return cost;
|
||||
}
|
||||
|
||||
qualificationConversion(cost);
|
||||
if (qualificationConversion(cost))
|
||||
return cost;
|
||||
|
||||
// If we can't convert the qualifications, then we can't do anything
|
||||
if (cost.qualification == Cost.NO_MATCH_RANK) {
|
||||
return cost;
|
||||
}
|
||||
cost.rank= Cost.NO_MATCH_RANK;
|
||||
return cost;
|
||||
|
||||
// Was the qualification conversion enough?
|
||||
IType s = getUltimateType(cost.source, true);
|
||||
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;
|
||||
// if (cost.rank == -1) {
|
||||
// relaxTemplateParameters(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.2] array-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 {
|
||||
Cost cost = new Cost(source, target);
|
||||
|
||||
if (!isCompleteType(source)) {
|
||||
cost.rank= Cost.NO_MATCH_RANK;
|
||||
return cost;
|
||||
}
|
||||
private static final boolean lvalue_to_rvalue(final Cost cost) throws DOMException {
|
||||
// target should not be a reference here.
|
||||
boolean isConverted= false;
|
||||
IType target = getNestedType(cost.target, REFERENCES | TYPEDEFS);
|
||||
IType source= getNestedType(cost.source, TYPEDEFS);
|
||||
|
||||
|
||||
// 4.1 lvalue to rvalue
|
||||
IType srcRValue= getNestedType(source, REFERENCES | TYPEDEFS);
|
||||
if (source instanceof ICPPReferenceType) {
|
||||
source= ((ICPPReferenceType) source).getType();
|
||||
while (source instanceof ITypedef)
|
||||
source = ((ITypedef) source).getType();
|
||||
// 4.1 lvalue of non-function and non-array
|
||||
if (!(srcRValue instanceof IFunctionType) && !(srcRValue instanceof IArrayType)) {
|
||||
// 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();
|
||||
cost.targetHadReference = true;
|
||||
|
||||
// 4.2 array to pointer conversion
|
||||
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
|
||||
if (target instanceof IPointerType && ((IPointerType) target).getType() instanceof IFunctionType &&
|
||||
source instanceof IFunctionType) {
|
||||
source = new CPPPointerType(source);
|
||||
} else if (target instanceof IPointerType && source instanceof IArrayType) {
|
||||
// 4.2 Array-To-Pointer conversion
|
||||
source = new CPPPointerType(((IArrayType) source).getType());
|
||||
if (!isConverted && target instanceof IPointerType) {
|
||||
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TYPEDEFS);
|
||||
if (targetPtrTgt instanceof IFunctionType && srcRValue instanceof IFunctionType) {
|
||||
source = new CPPPointerType(source);
|
||||
cost.rank= Cost.LVALUE_OR_QUALIFICATION_RANK;
|
||||
isConverted= true;
|
||||
}
|
||||
}
|
||||
|
||||
// 4.1 if T is a non-class type, the type of the rvalue is the cv-unqualified version of T
|
||||
if (source instanceof IQualifierType) {
|
||||
IType t = ((IQualifierType) source).getType();
|
||||
while (t instanceof ITypedef)
|
||||
t = ((ITypedef) t).getType();
|
||||
if (!(t instanceof ICPPClassType)) {
|
||||
source = t;
|
||||
// this should actually be done in 'checkImplicitConversionSequence', see 13.3.3.1-6 and 8.5.14
|
||||
// 8.5.14 cv-qualifiers can be ignored for non-class types
|
||||
IType unqualifiedTarget= getNestedType(target, QUALIFIERS | PTR_QUALIFIERS | TYPEDEFS | REFERENCES);
|
||||
if (!(unqualifiedTarget instanceof ICPPClassType)) {
|
||||
IType unqualifiedSource= getNestedType(source, QUALIFIERS | PTR_QUALIFIERS | TYPEDEFS | REFERENCES);
|
||||
if (!(unqualifiedSource instanceof ICPPClassType)) {
|
||||
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;
|
||||
cost.target = target;
|
||||
|
||||
return cost;
|
||||
if (source == null || target == null) {
|
||||
cost.rank= Cost.NO_MATCH_RANK;
|
||||
return true;
|
||||
}
|
||||
cost.source= source;
|
||||
cost.target= target;
|
||||
if (source.isSameType(target))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -555,136 +565,63 @@ public class Conversions {
|
|||
* @param cost
|
||||
* @throws DOMException
|
||||
*/
|
||||
private static final void qualificationConversion(Cost cost) throws DOMException{
|
||||
boolean canConvert = true;
|
||||
int requiredConversion = Cost.IDENTITY_RANK;
|
||||
|
||||
private static final boolean qualificationConversion(Cost cost) throws DOMException{
|
||||
IType s = cost.source;
|
||||
IType t = cost.target;
|
||||
boolean constInEveryCV2k = true;
|
||||
boolean firstPointer= true;
|
||||
boolean bothArePointers = false;
|
||||
boolean pointerNonPointerMismatch = false;
|
||||
while (true) {
|
||||
s= getUltimateTypeViaTypedefs(s);
|
||||
t= getUltimateTypeViaTypedefs(t);
|
||||
final boolean sourceIsPointer= s instanceof IPointerType;
|
||||
final boolean targetIsPointer= t instanceof IPointerType;
|
||||
|
||||
if (!targetIsPointer) {
|
||||
if (!sourceIsPointer && !(s instanceof IArrayType)) {
|
||||
break;
|
||||
}
|
||||
if (t instanceof ICPPBasicType) {
|
||||
if (((ICPPBasicType) t).getType() == ICPPBasicType.t_bool) {
|
||||
canConvert= true;
|
||||
requiredConversion = Cost.CONVERSION_RANK;
|
||||
break;
|
||||
s= getNestedType(s, TYPEDEFS | REFERENCES);
|
||||
t= getNestedType(t, TYPEDEFS | REFERENCES);
|
||||
if (s instanceof IPointerType && t instanceof IPointerType) {
|
||||
final int cmp= compareQualifications(t, s); // is t more qualified than s?
|
||||
if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
|
||||
return false;
|
||||
} else {
|
||||
final boolean sIsPtrToMember = s instanceof ICPPPointerToMemberType;
|
||||
final boolean tIsPtrToMember = t instanceof ICPPPointerToMemberType;
|
||||
if (sIsPtrToMember != tIsPtrToMember) {
|
||||
return false;
|
||||
} else if (sIsPtrToMember) {
|
||||
final IType sMemberOf = ((ICPPPointerToMemberType) s).getMemberOfClass();
|
||||
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 ((op1.isConst() && !op2.isConst()) || (op1.isVolatile() && !op2.isVolatile())) {
|
||||
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;
|
||||
if (cmp != 0) {
|
||||
cost.qualification= 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 {
|
||||
// 4.2-2 a string literal can be converted to pointer to char
|
||||
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();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cost.qualification = requiredConversion;
|
||||
if (canConvert) {
|
||||
cost.rank = Cost.LVALUE_OR_QUALIFICATION_RANK;
|
||||
}
|
||||
if (s instanceof IQualifierType || t instanceof IQualifierType) {
|
||||
int cmp= compareQualifications(t, s); // is t more qualified than s?
|
||||
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-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
|
||||
* @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 trg = cost.target;
|
||||
|
||||
if (src.isSameType(trg))
|
||||
return;
|
||||
boolean canPromote= false;
|
||||
if (trg instanceof IBasicType) {
|
||||
IBasicType basicTgt = (IBasicType) trg;
|
||||
final int tType = basicTgt.getType();
|
||||
|
||||
if (src instanceof IBasicType && trg instanceof IBasicType) {
|
||||
int sType = ((IBasicType) src).getType();
|
||||
int tType = ((IBasicType) trg).getType();
|
||||
if ((tType == IBasicType.t_int && (sType == IBasicType.t_int || // short, long, unsigned etc
|
||||
sType == IBasicType.t_char ||
|
||||
sType == ICPPBasicType.t_bool ||
|
||||
sType == ICPPBasicType.t_wchar_t ||
|
||||
sType == IBasicType.t_unspecified)) || // treat unspecified as int
|
||||
(tType == IBasicType.t_double && sType == IBasicType.t_float)) {
|
||||
cost.promotion = 1;
|
||||
if (src instanceof IBasicType) {
|
||||
final IBasicType basicSrc = (IBasicType) src;
|
||||
int sType = basicSrc.getType();
|
||||
if (tType == IBasicType.t_int) {
|
||||
switch (sType) {
|
||||
case IBasicType.t_int: // short, and unsigned short
|
||||
if (basicSrc.isShort()) {
|
||||
canPromote= true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
cost.rank = (cost.promotion > 0) ? Cost.PROMOTION_RANK : Cost.NO_MATCH_RANK;
|
||||
if (canPromote) {
|
||||
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.8] Floating point conversions
|
||||
* [4.9] Floating-integral conversions
|
||||
* [4.10] Pointer conversions
|
||||
* [4.11] Pointer to member conversions
|
||||
* @param cost
|
||||
* @throws DOMException
|
||||
*/
|
||||
private static final void conversion(Cost cost) throws DOMException{
|
||||
final IType src = cost.source;
|
||||
final IType trg = cost.target;
|
||||
private static final boolean conversion(Cost cost, boolean forImplicitThis) throws DOMException{
|
||||
final IType s = cost.source;
|
||||
final IType t = cost.target;
|
||||
|
||||
cost.conversion = 0;
|
||||
cost.detail = 0;
|
||||
|
||||
IType[] sHolder= new IType[1], tHolder= new IType[1];
|
||||
IType s = getUltimateType(src, sHolder, true);
|
||||
IType t = getUltimateType(trg, tHolder, true);
|
||||
IType sPrev= sHolder[0], tPrev= tHolder[0];
|
||||
|
||||
if (src instanceof CPPBasicType && trg instanceof IPointerType) {
|
||||
// 4.10-1 an integral constant expression of integer type that evaluates to 0 can
|
||||
// be converted to a pointer type
|
||||
IASTExpression exp = ((CPPBasicType) src).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;
|
||||
}
|
||||
}
|
||||
} 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) {
|
||||
|
||||
if (t instanceof IBasicType) {
|
||||
// 4.7 integral conversion
|
||||
// 4.8 floating point conversion
|
||||
// 4.9 floating-integral conversion
|
||||
if (s instanceof IBasicType || s instanceof IEnumeration) {
|
||||
// 4.7 An rvalue of an integer type can be converted to an rvalue of another integer type.
|
||||
// An rvalue of an enumeration type can be converted to an rvalue of an integer type.
|
||||
cost.rank = Cost.CONVERSION_RANK;
|
||||
cost.conversion = 1;
|
||||
return true;
|
||||
}
|
||||
// 4.12 pointer or pointer to member type can be converted to an rvalue of type bool
|
||||
final int tgtType = ((IBasicType) t).getType();
|
||||
if (tgtType == ICPPBasicType.t_bool && s instanceof IPointerType) {
|
||||
cost.rank = Cost.CONVERSION_RANK;
|
||||
cost.conversion = 1;
|
||||
cost.detail = 2;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// to an rvalue of type "pointer to cv B", where B is a base class of D.
|
||||
else if (s instanceof ICPPClassType && tPrev instanceof IPointerType && t instanceof ICPPClassType) {
|
||||
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, s, t);
|
||||
cost.rank= (depth > -1) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK;
|
||||
cost.conversion= (depth > -1) ? depth : 0;
|
||||
cost.detail= 1;
|
||||
return;
|
||||
}
|
||||
// 4.12 if the target is a bool, we can still convert
|
||||
else if (!(trg instanceof IBasicType && ((IBasicType) trg).getType() == ICPPBasicType.t_bool)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (t instanceof IBasicType && (s instanceof IBasicType || s instanceof IEnumeration)) {
|
||||
// 4.7 An rvalue of an integer type can be converted to an rvalue of another integer type.
|
||||
// An rvalue of an enumeration type can be converted to an rvalue of an integer type.
|
||||
cost.rank = Cost.CONVERSION_RANK;
|
||||
cost.conversion = 1;
|
||||
} else if (trg instanceof IBasicType && ((IBasicType) trg).getType() == ICPPBasicType.t_bool &&
|
||||
s instanceof IPointerType) {
|
||||
// 4.12 pointer or pointer to member type can be converted to an rvalue of type bool
|
||||
cost.rank = Cost.CONVERSION_RANK;
|
||||
cost.conversion = 1;
|
||||
} 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,
|
||||
// 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());
|
||||
cost.rank= (depth > -1) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK;
|
||||
cost.conversion= (depth > -1) ? depth : 0;
|
||||
cost.detail= 1;
|
||||
if (s instanceof IPointerType) {
|
||||
IPointerType srcPtr= (IPointerType) s;
|
||||
// 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"
|
||||
IType tgtPtrTgt= getNestedType(tgtPtr.getType(), TYPEDEFS | QUALIFIERS | REFERENCES);
|
||||
if (tgtPtrTgt instanceof IBasicType && ((IBasicType) tgtPtrTgt).getType() == IBasicType.t_void) {
|
||||
cost.rank = Cost.CONVERSION_RANK;
|
||||
cost.conversion = 1;
|
||||
cost.detail = 2;
|
||||
int cv= getCVQualifier(srcPtr.getType());
|
||||
cost.source= new CPPPointerType(addQualifiers(CPPSemantics.VOID_TYPE, (cv&1) != 0, (cv&2) != 0));
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean tIsPtrToMember = t instanceof ICPPPointerToMemberType;
|
||||
final boolean sIsPtrToMember = s instanceof ICPPPointerToMemberType;
|
||||
if (!tIsPtrToMember && !sIsPtrToMember) {
|
||||
// 4.10-3 An rvalue of type "pointer to cv D", where D is a class type can be converted
|
||||
// to an rvalue of type "pointer to cv B", where B is a base class of D.
|
||||
IType srcPtrTgt= getNestedType(srcPtr.getType(), TYPEDEFS | QUALIFIERS | REFERENCES);
|
||||
if (tgtPtrTgt instanceof ICPPClassType && srcPtrTgt instanceof ICPPClassType) {
|
||||
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, srcPtrTgt, tgtPtrTgt);
|
||||
if (depth == -1) {
|
||||
cost.rank= Cost.NO_MATCH_RANK;
|
||||
return true;
|
||||
}
|
||||
if (depth > 0) {
|
||||
if (!forImplicitThis) {
|
||||
cost.rank= Cost.CONVERSION_RANK;
|
||||
cost.conversion= depth;
|
||||
}
|
||||
cost.detail= 1;
|
||||
int cv= getCVQualifier(srcPtr.getType());
|
||||
cost.source= new CPPPointerType(addQualifiers(tgtPtrTgt, (cv&1) != 0, (cv&2) != 0));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else if (tIsPtrToMember && sIsPtrToMember) {
|
||||
// 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
|
||||
* @return whether the specified type has an associated definition
|
||||
|
@ -850,17 +819,22 @@ public class Conversions {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows any very loose matching between template parameters.
|
||||
* @param cost
|
||||
*/
|
||||
private static final void relaxTemplateParameters(Cost cost) {
|
||||
IType s = getUltimateType(cost.source, false);
|
||||
IType t = getUltimateType(cost.target, false);
|
||||
|
||||
if ((s instanceof ICPPTemplateTypeParameter && t instanceof ICPPTemplateTypeParameter) ||
|
||||
(s instanceof ICPPTemplateTemplateParameter && t instanceof ICPPTemplateTemplateParameter)) {
|
||||
cost.rank = Cost.FUZZY_TEMPLATE_PARAMETERS;
|
||||
}
|
||||
}
|
||||
// mstodo must be part of implicit conversion
|
||||
// /**
|
||||
// * [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 (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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -42,8 +42,6 @@ class Cost {
|
|||
public IType source;
|
||||
public IType target;
|
||||
|
||||
public boolean targetHadReference = false;
|
||||
|
||||
public int lvalue;
|
||||
public int promotion;
|
||||
public int conversion;
|
||||
|
@ -108,11 +106,7 @@ class Cost {
|
|||
op2 = null;
|
||||
while (true) {
|
||||
if (t1 instanceof ITypedef) {
|
||||
try {
|
||||
t1 = ((ITypedef) t1).getType();
|
||||
} catch (DOMException e) {
|
||||
t1 = e.getProblem();
|
||||
}
|
||||
t1 = ((ITypedef) t1).getType();
|
||||
} else {
|
||||
if (t1 instanceof IPointerType)
|
||||
op1 = (IPointerType) t1;
|
||||
|
@ -121,11 +115,7 @@ class Cost {
|
|||
}
|
||||
while (true) {
|
||||
if (t2 instanceof ITypedef) {
|
||||
try {
|
||||
t2 = ((ITypedef) t2).getType();
|
||||
} catch (DOMException e) {
|
||||
t2 = e.getProblem();
|
||||
}
|
||||
t2 = ((ITypedef) t2).getType();
|
||||
} else {
|
||||
if (t2 instanceof IPointerType)
|
||||
op2 = (IPointerType) t2;
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
|||
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.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.CPPQualifierType;
|
||||
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 REFERENCES = 0x2;
|
||||
static final int QUALIFIERS = 0x4;
|
||||
static final int PTR_QUALIFIERS= 0x8;
|
||||
|
||||
static {
|
||||
final int OPERATOR_SPC= OPERATOR_CHARS.length + 1;
|
||||
|
@ -161,50 +164,32 @@ public class SemanticUtil {
|
|||
* @return the deepest type in a type container sequence
|
||||
*/
|
||||
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
|
||||
* pointer-to-member types.
|
||||
|
@ -245,6 +230,8 @@ public class SemanticUtil {
|
|||
public static IType getNestedType(IType type, int options) {
|
||||
boolean typedefs= (options & TYPEDEFS) != 0;
|
||||
boolean refs= (options & REFERENCES) != 0;
|
||||
boolean qualifiers= (options & QUALIFIERS) != 0;
|
||||
boolean ptrQualifiers= (options & PTR_QUALIFIERS) != 0;
|
||||
try {
|
||||
while (true) {
|
||||
IType t= null;
|
||||
|
@ -252,6 +239,22 @@ public class SemanticUtil {
|
|||
t= ((ITypedef) type).getType();
|
||||
} else if (refs && type instanceof ICPPReferenceType) {
|
||||
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)
|
||||
return type;
|
||||
|
@ -378,36 +381,58 @@ public class SemanticUtil {
|
|||
* Adjusts the parameter type according to 8.3.5-3:
|
||||
* 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
|
||||
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
|
||||
//Any cv-qualifier modifying a parameter type is deleted.
|
||||
//so only create the base type from the declspec and not the qualifiers
|
||||
try {
|
||||
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);
|
||||
if (forFunctionType && (t instanceof IQualifierType || t instanceof IPointerType)) {
|
||||
return SemanticUtil.getNestedType(t, TYPEDEFS | QUALIFIERS | PTR_QUALIFIERS);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue