mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 09:25:31 +02:00
Bug 327328: Overload resolution and restrict pointers.
This commit is contained in:
parent
4473ddf01f
commit
64778c5409
15 changed files with 192 additions and 165 deletions
|
@ -9207,4 +9207,43 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
assertSame(ctor2, dtor.getImplicitNames()[0].resolveBinding());
|
||||
}
|
||||
|
||||
// void g(int * __restrict a);
|
||||
// void g(int * a) {}
|
||||
//
|
||||
// void test1() {
|
||||
// int number = 5;
|
||||
// g(&number);
|
||||
// }
|
||||
public void testTopLevelRestrictQualifier_327328() throws Exception {
|
||||
String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
IFunction g= bh.assertNonProblem("g(int * __restrict a)", 1);
|
||||
IFunction ref;
|
||||
ref= bh.assertNonProblem("g(int * a)", 1);
|
||||
assertSame(g, ref);
|
||||
ref= bh.assertNonProblem("g(&number)", 1);
|
||||
assertSame(g, ref);
|
||||
}
|
||||
|
||||
// void f(int * __restrict* a) {}
|
||||
// void f(int ** a) {} // different function
|
||||
//
|
||||
// void test2() {
|
||||
// int* __restrict rnumber= 0;
|
||||
// int* number = 0;
|
||||
// f(&rnumber); // calls f(int* __restrict* a)
|
||||
// f(&number); // calls f(int** a)
|
||||
// }
|
||||
public void testOverloadingWithRestrictQualifier_327328() throws Exception {
|
||||
String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
IFunction f1= bh.assertNonProblem("f(int * __restrict* a)", 1);
|
||||
IFunction f2= bh.assertNonProblem("f(int ** a)", 1);
|
||||
IFunction ref;
|
||||
ref= bh.assertNonProblem("f(&rnumber)", 1);
|
||||
assertSame(f1, ref);
|
||||
ref= bh.assertNonProblem("f(&number)", 1);
|
||||
assertSame(f2, ref);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import java.util.List;
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICArrayType;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICQualifierType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
|
||||
|
@ -32,7 +31,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPQualifierType;
|
||||
import org.eclipse.cdt.core.parser.Keywords;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
|
@ -368,7 +366,7 @@ public class ASTTypeUtil {
|
|||
}
|
||||
if (type instanceof ICPPFunctionType) {
|
||||
ICPPFunctionType ft= (ICPPFunctionType) type;
|
||||
needSpace= appendCVQ(result, needSpace, ft.isConst(), ft.isVolatile());
|
||||
needSpace= appendCVQ(result, needSpace, ft.isConst(), ft.isVolatile(), false);
|
||||
}
|
||||
} else if (type instanceof IPointerType) {
|
||||
if (type instanceof ICPPPointerToMemberType) {
|
||||
|
@ -376,25 +374,8 @@ public class ASTTypeUtil {
|
|||
result.append(Keywords.cpCOLONCOLON);
|
||||
}
|
||||
result.append(Keywords.cpSTAR); needSpace = true;
|
||||
|
||||
if (type instanceof IGPPPointerType) {
|
||||
if (((IGPPPointerType) type).isRestrict()) {
|
||||
if (needSpace) {
|
||||
result.append(SPACE); needSpace = false;
|
||||
}
|
||||
result.append(Keywords.RESTRICT); needSpace = true;
|
||||
}
|
||||
} else if (type instanceof ICPointerType) {
|
||||
if (((ICPointerType) type).isRestrict()) {
|
||||
if (needSpace) {
|
||||
result.append(SPACE); needSpace = false;
|
||||
}
|
||||
result.append(Keywords.RESTRICT); needSpace = true;
|
||||
}
|
||||
}
|
||||
|
||||
IPointerType pt= (IPointerType) type;
|
||||
needSpace= appendCVQ(result, needSpace, pt.isConst(), pt.isVolatile());
|
||||
needSpace= appendCVQ(result, needSpace, pt.isConst(), pt.isVolatile(), pt.isRestrict());
|
||||
} else if (type instanceof IQualifierType) {
|
||||
if (type instanceof ICQualifierType) {
|
||||
if (((ICQualifierType) type).isRestrict()) {
|
||||
|
@ -407,7 +388,7 @@ public class ASTTypeUtil {
|
|||
}
|
||||
|
||||
IQualifierType qt= (IQualifierType) type;
|
||||
needSpace= appendCVQ(result, needSpace, qt.isConst(), qt.isVolatile());
|
||||
needSpace= appendCVQ(result, needSpace, qt.isConst(), qt.isVolatile(), false);
|
||||
} else if (type instanceof ITypedef) {
|
||||
result.append(((ITypedef) type).getNameCharArray());
|
||||
} else if (type instanceof ISemanticProblem) {
|
||||
|
@ -420,18 +401,27 @@ public class ASTTypeUtil {
|
|||
}
|
||||
|
||||
private static boolean appendCVQ(StringBuilder target, boolean needSpace, final boolean isConst,
|
||||
final boolean isVolatile) {
|
||||
final boolean isVolatile, final boolean isRestrict) {
|
||||
if (isConst) {
|
||||
if (needSpace) {
|
||||
target.append(SPACE); needSpace = false;
|
||||
target.append(SPACE);
|
||||
}
|
||||
target.append(Keywords.CONST); needSpace = true;
|
||||
target.append(Keywords.CONST);
|
||||
needSpace = true;
|
||||
}
|
||||
if (isVolatile) {
|
||||
if (needSpace) {
|
||||
target.append(SPACE); needSpace = false;
|
||||
target.append(SPACE);
|
||||
}
|
||||
target.append(Keywords.VOLATILE); needSpace = true;
|
||||
target.append(Keywords.VOLATILE);
|
||||
needSpace = true;
|
||||
}
|
||||
if (isRestrict) {
|
||||
if (needSpace) {
|
||||
target.append(SPACE);
|
||||
}
|
||||
target.append(Keywords.RESTRICT);
|
||||
needSpace = true;
|
||||
}
|
||||
return needSpace;
|
||||
}
|
||||
|
@ -492,7 +482,7 @@ public class ASTTypeUtil {
|
|||
if (cvq != null) {
|
||||
// merge cv qualifiers
|
||||
if (type instanceof IQualifierType || type instanceof IPointerType) {
|
||||
type= SemanticUtil.addQualifiers(type, cvq.isConst(), cvq.isVolatile());
|
||||
type= SemanticUtil.addQualifiers(type, cvq.isConst(), cvq.isVolatile(), false);
|
||||
cvq= null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -248,15 +248,15 @@ public class CPPASTFieldReference extends ASTNode implements ICPPASTFieldReferen
|
|||
|
||||
public static IType addQualifiersForAccess(ICPPField field, IType fieldType, IType ownerType) {
|
||||
CVQualifier cvq1 = SemanticUtil.getCVQualifier(ownerType);
|
||||
CVQualifier cvq2 = SemanticUtil.getCVQualifier(fieldType);
|
||||
if (field.isMutable()) {
|
||||
// Remove const, add union of volatile.
|
||||
CVQualifier cvq2 = SemanticUtil.getCVQualifier(fieldType);
|
||||
if (cvq2.isConst()) {
|
||||
fieldType= SemanticUtil.getNestedType(fieldType, ALLCVQ | TDEF | REF);
|
||||
}
|
||||
fieldType= SemanticUtil.addQualifiers(fieldType, false, cvq1.isVolatile() || cvq2.isVolatile());
|
||||
fieldType= SemanticUtil.addQualifiers(fieldType, false, cvq1.isVolatile() || cvq2.isVolatile(), cvq2.isRestrict());
|
||||
} else {
|
||||
fieldType= SemanticUtil.addQualifiers(fieldType, cvq1.isConst(), cvq1.isVolatile());
|
||||
fieldType= SemanticUtil.addQualifiers(fieldType, cvq1.isConst(), cvq1.isVolatile(), cvq2.isRestrict());
|
||||
}
|
||||
return fieldType;
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
|||
char[] className = name.getLookupKey();
|
||||
|
||||
ICPPParameter[] voidPs = new ICPPParameter[] { new CPPParameter(CPPSemantics.VOID_TYPE, 0) };
|
||||
IType pType = new CPPReferenceType(SemanticUtil.addQualifiers(clsType, true, false), false);
|
||||
IType pType = new CPPReferenceType(SemanticUtil.constQualify(clsType), false);
|
||||
ICPPParameter[] ps = new ICPPParameter[] { new CPPParameter(pType, 0) };
|
||||
|
||||
int i= 0;
|
||||
|
|
|
@ -80,7 +80,7 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
|
|||
result[0]= ctor;
|
||||
|
||||
// Copy constructor: A(const A &)
|
||||
IType pType = new CPPReferenceType(SemanticUtil.addQualifiers(this, true, false), false);
|
||||
IType pType = new CPPReferenceType(SemanticUtil.constQualify(this), false);
|
||||
ICPPParameter[] ps = new ICPPParameter[] { new CPPParameter(pType, 0) };
|
||||
ctor = new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, ps);
|
||||
result[1]= ctor;
|
||||
|
|
|
@ -359,7 +359,7 @@ class BuiltinOperators {
|
|||
if (SemanticUtil.calculateInheritanceDepth(c1, c2) >= 0) {
|
||||
IType cvt= SemanticUtil.getNestedType(memPtr.getType(), TDEF);
|
||||
IType rt= new CPPReferenceType(
|
||||
SemanticUtil.addQualifiers(cvt, cv1.isConst(), cv1.isVolatile()), false);
|
||||
SemanticUtil.addQualifiers(cvt, cv1.isConst(), cv1.isVolatile(), cv1.isRestrict()), false);
|
||||
addFunction(rt, clsPtr, memPtr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -761,7 +761,6 @@ public class CPPSemantics {
|
|||
if (scope instanceof ICPPScope) {
|
||||
return (ICPPScope) scope;
|
||||
} else if (scope instanceof IProblemBinding) {
|
||||
// mstodo scope problems
|
||||
return new CPPScope.CPPScopeProblem(((IProblemBinding) scope).getASTNode(),
|
||||
IProblemBinding.SEMANTIC_BAD_SCOPE, ((IProblemBinding) scope).getNameCharArray());
|
||||
}
|
||||
|
@ -2527,7 +2526,7 @@ public class CPPSemantics {
|
|||
IType impliedObjectType= null;
|
||||
final IType[] paramTypes= ftype.getParameterTypes();
|
||||
if (fn instanceof ICPPMethod && !(fn instanceof ICPPConstructor)) {
|
||||
implicitParameterType = getImplicitParameterType((ICPPMethod) fn, ftype.isConst(), ftype.isVolatile());
|
||||
implicitParameterType = getImplicitParameterType((ICPPMethod) fn);
|
||||
if (data.argsContainImpliedObject) {
|
||||
impliedObjectType= argTypes[0];
|
||||
skipArg= 1;
|
||||
|
@ -2623,16 +2622,15 @@ public class CPPSemantics {
|
|||
return result;
|
||||
}
|
||||
|
||||
static IType getImplicitParameterType(ICPPMethod m, final boolean isConst, final boolean isVolatile)
|
||||
throws DOMException {
|
||||
static IType getImplicitParameterType(ICPPMethod m) throws DOMException {
|
||||
IType implicitType;
|
||||
ICPPClassType owner= m.getClassOwner();
|
||||
if (owner instanceof ICPPClassTemplate) {
|
||||
owner= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) owner);
|
||||
}
|
||||
implicitType= SemanticUtil.addQualifiers(owner, isConst, isVolatile);
|
||||
implicitType= new CPPReferenceType(implicitType, false);
|
||||
return implicitType;
|
||||
ICPPFunctionType ft= m.getType();
|
||||
implicitType= SemanticUtil.addQualifiers(owner, ft.isConst(), ft.isVolatile(), false);
|
||||
return new CPPReferenceType(implicitType, false);
|
||||
}
|
||||
|
||||
private static IBinding resolveUserDefinedConversion(LookupData data, IFunction[] fns) {
|
||||
|
@ -2907,14 +2905,6 @@ public class CPPSemantics {
|
|||
return foundOperator ? type : null;
|
||||
}
|
||||
|
||||
private static ICPPVariable createVariable(IASTName name, final IType type, final boolean isConst, final boolean isVolatile) {
|
||||
return new CPPVariable(name) {
|
||||
@Override public IType getType() {
|
||||
return SemanticUtil.addQualifiers(type, isConst, isVolatile);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
|
||||
final IASTExpression arrayExpression = exp.getArrayExpression();
|
||||
IASTInitializerClause[] args = {arrayExpression, exp.getArgument()};
|
||||
|
@ -3118,9 +3108,13 @@ public class CPPSemantics {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static IASTExpression createArgForType(IASTNode node, IType type) {
|
||||
public static IASTExpression createArgForType(IASTNode node, final IType type) {
|
||||
CPPASTName x= new CPPASTName();
|
||||
x.setBinding(createVariable(x, type, false, false));
|
||||
x.setBinding(new CPPVariable(x) {
|
||||
@Override public IType getType() {
|
||||
return type;
|
||||
}
|
||||
});
|
||||
final CPPASTIdExpression idExpression = new CPPASTIdExpression(x);
|
||||
idExpression.setParent(node);
|
||||
return idExpression;
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.addQualifiers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -121,7 +120,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodTemplateSpecializat
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterPackType;
|
||||
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.CPPReferenceType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateDefinition;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeParameter;
|
||||
|
@ -1759,9 +1757,9 @@ public class CPPTemplates {
|
|||
boolean nonStaticMember2= isNonStaticMember(f2);
|
||||
if (nonStaticMember1 != nonStaticMember2) {
|
||||
if (nonStaticMember1) {
|
||||
args= addImplicitObjectType(args, (ICPPMethod) f1);
|
||||
args= addImplicitParameterType(args, (ICPPMethod) f1);
|
||||
} else {
|
||||
pars= addImplicitObjectType(pars, (ICPPMethod) f2);
|
||||
pars= addImplicitParameterType(pars, (ICPPMethod) f2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1773,14 +1771,13 @@ public class CPPTemplates {
|
|||
return (f instanceof ICPPMethod) && !((ICPPMethod) f).isStatic();
|
||||
}
|
||||
|
||||
private static IType[] addImplicitObjectType(IType[] types, ICPPMethod f1) {
|
||||
ICPPClassType ct = f1.getClassOwner();
|
||||
if (ct != null) {
|
||||
ICPPFunctionType ft = f1.getType();
|
||||
final CPPReferenceType t = new CPPReferenceType(addQualifiers(ct, ft.isConst(), ft.isVolatile()), false);
|
||||
private static IType[] addImplicitParameterType(IType[] types, ICPPMethod m) {
|
||||
try {
|
||||
IType t= CPPSemantics.getImplicitParameterType(m);
|
||||
return concat(t, types);
|
||||
} catch (DOMException e) {
|
||||
return types;
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
private static IType[] concat(final IType t, IType[] types) {
|
||||
|
|
|
@ -1670,7 +1670,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
// 8.3.5-3
|
||||
// Any cv-qualifier modifying a parameter type is deleted. The parameter type remains
|
||||
// to be qualified.
|
||||
if (forFunctionType && SemanticUtil.getCVQualifier(t) != CVQualifier._) {
|
||||
if (forFunctionType && SemanticUtil.getCVQualifier(t) != CVQualifier.NONE) {
|
||||
return SemanticUtil.getNestedType(t, TDEF | ALLCVQ);
|
||||
}
|
||||
return pt;
|
||||
|
@ -1879,7 +1879,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
}
|
||||
|
||||
private static IType qualifyType(IType type, IASTDeclSpecifier declSpec) {
|
||||
return SemanticUtil.addQualifiers(type, declSpec.isConst(), declSpec.isVolatile());
|
||||
return SemanticUtil.addQualifiers(type, declSpec.isConst(), declSpec.isVolatile(), declSpec.isRestrict());
|
||||
}
|
||||
|
||||
private static IType createType(IType baseType, IASTDeclarator declarator) {
|
||||
|
@ -1977,7 +1977,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
if (type instanceof ICPPClassTemplate) {
|
||||
type= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) type);
|
||||
}
|
||||
return SemanticUtil.addQualifiers(type, dtor.isConst(), dtor.isVolatile());
|
||||
return SemanticUtil.addQualifiers(type, dtor.isConst(), dtor.isVolatile(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 Wind River Systems, Inc. and others.
|
||||
* Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -10,49 +10,85 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
|
||||
/**
|
||||
* Represents the possible cv-qualification of a type.
|
||||
*/
|
||||
public enum CVQualifier {
|
||||
cv(true, true), c(true, false), v(false, true), _(false, false);
|
||||
CONST_VOLATILE_RESTRICT(1 | 2 | 4), CONST_VOLATILE(1 | 2), CONST_RESTRICT(1 | 4), CONST(1),
|
||||
VOLATILE_RESTRICT(2 | 4), VOLATILE(2), RESTRICT(4), NONE(0);
|
||||
|
||||
final private boolean fConst;
|
||||
final private boolean fVolatile;
|
||||
|
||||
private CVQualifier(boolean c, boolean v) {
|
||||
fConst= c;
|
||||
fVolatile= v;
|
||||
private static final int C = 1;
|
||||
private static final int V = 2;
|
||||
private static final int R = 4;
|
||||
|
||||
final private int fQualifiers;
|
||||
private CVQualifier(int qualifiers) {
|
||||
fQualifiers= qualifiers;
|
||||
}
|
||||
|
||||
public boolean isConst() {
|
||||
return fConst;
|
||||
return (fQualifiers & C) != 0;
|
||||
}
|
||||
public boolean isVolatile() {
|
||||
return fVolatile;
|
||||
return (fQualifiers & V) != 0;
|
||||
}
|
||||
public boolean isRestrict() {
|
||||
return (fQualifiers & R) != 0;
|
||||
}
|
||||
|
||||
public boolean isAtLeastAsQualifiedAs(CVQualifier other) {
|
||||
return other == _ || this == other || this == cv;
|
||||
return (fQualifiers | other.fQualifiers) == fQualifiers;
|
||||
}
|
||||
|
||||
public boolean isMoreQualifiedThan(CVQualifier other) {
|
||||
return this != other && (other == _ || this == cv);
|
||||
return this != other && isAtLeastAsQualifiedAs(other);
|
||||
}
|
||||
|
||||
public CVQualifier remove(CVQualifier arg) {
|
||||
if (this == arg)
|
||||
return _;
|
||||
|
||||
switch (arg) {
|
||||
case _:
|
||||
return this;
|
||||
case c:
|
||||
return isVolatile() ? v : _;
|
||||
case v:
|
||||
return isConst() ? c : _;
|
||||
case cv:
|
||||
return _;
|
||||
public CVQualifier add(CVQualifier cvq) {
|
||||
return fromQualifier(fQualifiers | cvq.fQualifiers);
|
||||
}
|
||||
|
||||
public CVQualifier remove(CVQualifier cvq) {
|
||||
return fromQualifier(fQualifiers & ~cvq.fQualifiers);
|
||||
}
|
||||
|
||||
private CVQualifier fromQualifier(final int q) {
|
||||
switch(q) {
|
||||
case C|V|R: return CONST_VOLATILE_RESTRICT;
|
||||
case V|R: return VOLATILE_RESTRICT;
|
||||
case C|R: return CONST_RESTRICT;
|
||||
case R: return RESTRICT;
|
||||
case C|V: return CONST_VOLATILE;
|
||||
case V: return VOLATILE;
|
||||
case C: return CONST;
|
||||
case 0: default: return NONE;
|
||||
}
|
||||
return _;
|
||||
}
|
||||
|
||||
/**
|
||||
* [3.9.3-4] Implements cv-qualification (partial) comparison. There is a (partial)
|
||||
* ordering on cv-qualifiers, so that a type can be said to be more
|
||||
* cv-qualified than another.
|
||||
* @return <ul>
|
||||
* <li>7 if cv1 == const volatile restrict cv2
|
||||
* <li>6 if cv1 == volatile restrict cv2
|
||||
* <li>5 if cv1 == const restrict cv2
|
||||
* <li>4 if cv1 == restrict cv2
|
||||
* <li>3 if cv1 == const volatile cv2
|
||||
* <li>2 if cv1 == volatile cv2
|
||||
* <li>1 if cv1 == const cv2
|
||||
* <li>EQ 0 if cv1 == cv2
|
||||
* <li>LT -1 if cv1 is less qualified than cv2 or not comparable
|
||||
* </ul>
|
||||
*/
|
||||
public int partialComparison(CVQualifier cv2) {
|
||||
// same qualifications
|
||||
if (this == cv2)
|
||||
return 0;
|
||||
|
||||
if (!isAtLeastAsQualifiedAs(cv2))
|
||||
return -1;
|
||||
return fQualifiers-cv2.fQualifiers;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier._;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromReturnType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
|
||||
|
@ -113,7 +112,7 @@ public class Conversions {
|
|||
}
|
||||
|
||||
if (exprType instanceof InitializerListType) {
|
||||
if (isLValueRef && getCVQualifier(cv1T1) != CVQualifier.c)
|
||||
if (isLValueRef && getCVQualifier(cv1T1) != CVQualifier.CONST)
|
||||
return Cost.NO_CONVERSION;
|
||||
|
||||
Cost cost= listInitializationSequence(((InitializerListType) exprType), T1, udc, false);
|
||||
|
@ -157,7 +156,7 @@ public class Conversions {
|
|||
// shall be an rvalue or have function type.
|
||||
boolean ok;
|
||||
if (isLValueRef) {
|
||||
ok = getCVQualifier(cv1T1) == CVQualifier.c;
|
||||
ok = getCVQualifier(cv1T1) == CVQualifier.CONST;
|
||||
} else {
|
||||
ok= valueCat.isRValue() || T2 instanceof IFunctionType;
|
||||
}
|
||||
|
@ -272,7 +271,7 @@ public class Conversions {
|
|||
IType t= getNestedType(ft.getReturnType(), TDEF);
|
||||
final boolean isLValueRef= t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference();
|
||||
if (isLValueRef == needLValue) { // require an lvalue or rvalue
|
||||
IType implicitParameterType= CPPSemantics.getImplicitParameterType(op, ft.isConst(), ft.isVolatile());
|
||||
IType implicitParameterType= CPPSemantics.getImplicitParameterType(op);
|
||||
Cost udcCost= isReferenceCompatible(getNestedType(implicitParameterType, TDEF | REF), cv2T2, true); // expression type to implicit object type
|
||||
if (udcCost != null) {
|
||||
// Make sure top-level cv-qualifiers are compared
|
||||
|
@ -429,30 +428,7 @@ public class Conversions {
|
|||
* </ul>
|
||||
*/
|
||||
private static final int compareQualifications(IType t1, IType t2) {
|
||||
CVQualifier cv1= getCVQualifier(t1);
|
||||
CVQualifier cv2= getCVQualifier(t2);
|
||||
|
||||
// same qualifications
|
||||
if (cv1 == cv2)
|
||||
return 0;
|
||||
|
||||
switch (cv1) {
|
||||
case cv:
|
||||
switch (cv2) {
|
||||
case _: return 3;
|
||||
case c: return 2;
|
||||
case v: return 1;
|
||||
case cv: return 0;
|
||||
}
|
||||
break;
|
||||
case c:
|
||||
return cv2 == _ ? 1 : -1;
|
||||
case v:
|
||||
return cv2 == _ ? 2 : -1;
|
||||
case _:
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
return getCVQualifier(t1).partialComparison(getCVQualifier(t2));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -723,8 +699,7 @@ public class Conversions {
|
|||
final IType uqReturnType= getNestedType(returnType, REF | TDEF | CVTYPE);
|
||||
final int dist = SemanticUtil.calculateInheritanceDepth(uqReturnType, t);
|
||||
if (dist >= 0) {
|
||||
final ICPPFunctionType ft = op.getType();
|
||||
IType implicitType= CPPSemantics.getImplicitParameterType(op, ft.isConst(), ft.isVolatile());
|
||||
IType implicitType= CPPSemantics.getImplicitParameterType(op);
|
||||
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
|
||||
if (udcCost != null) {
|
||||
// Make sure top-level cv-qualifiers are compared
|
||||
|
@ -779,8 +754,7 @@ public class Conversions {
|
|||
if (c2.converts()) {
|
||||
if (isExplicitConversion && c2.getRank() != Rank.IDENTITY)
|
||||
continue;
|
||||
ICPPFunctionType ftype = op.getType();
|
||||
IType implicitType= CPPSemantics.getImplicitParameterType(op, ftype.isConst(), ftype.isVolatile());
|
||||
IType implicitType= CPPSemantics.getImplicitParameterType(op);
|
||||
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
|
||||
if (udcCost != null) {
|
||||
// Make sure top-level cv-qualifiers are compared
|
||||
|
@ -870,7 +844,8 @@ public class Conversions {
|
|||
IASTLiteralExpression lit= (IASTLiteralExpression) val;
|
||||
if (lit.getKind() == IASTLiteralExpression.lk_string_literal) {
|
||||
source= new CPPPointerType(srcTarget, false, false, false);
|
||||
cost.setQualificationAdjustment((getCVQualifier(targetPtrTgt).isVolatile() ? 2 : 1) << 2);
|
||||
CVQualifier cvqTarget = getCVQualifier(targetPtrTgt).add(CVQualifier.CONST);
|
||||
cost.setQualificationAdjustment(cvqTarget.partialComparison(CVQualifier.NONE) << 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -907,7 +882,7 @@ public class Conversions {
|
|||
t= tPtr.getType();
|
||||
firstPointer= false;
|
||||
adjustments |= (cmp << shift);
|
||||
shift+= 2;
|
||||
shift+= 3;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -1092,7 +1067,7 @@ public class Conversions {
|
|||
cost.setRank(Rank.CONVERSION);
|
||||
cost.setInheritanceDistance(Short.MAX_VALUE);
|
||||
CVQualifier cv= getCVQualifier(srcPtr.getType());
|
||||
cost.source= new CPPPointerType(addQualifiers(CPPSemantics.VOID_TYPE, cv.isConst(), cv.isVolatile()));
|
||||
cost.source= new CPPPointerType(addQualifiers(CPPSemantics.VOID_TYPE, cv.isConst(), cv.isVolatile(), cv.isRestrict()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1114,7 +1089,7 @@ public class Conversions {
|
|||
cost.setInheritanceDistance(depth);
|
||||
}
|
||||
CVQualifier cv= getCVQualifier(srcPtr.getType());
|
||||
cost.source= new CPPPointerType(addQualifiers(tgtPtrTgt, cv.isConst(), cv.isVolatile()));
|
||||
cost.source= new CPPPointerType(addQualifiers(tgtPtrTgt, cv.isConst(), cv.isVolatile(), cv.isRestrict()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1205,11 +1180,11 @@ public class Conversions {
|
|||
|
||||
final IType target1 = p1.getType();
|
||||
if (isVoidType(target1)) {
|
||||
return addQualifiers(p1, p2.isConst(), p2.isVolatile());
|
||||
return addQualifiers(p1, p2.isConst(), p2.isVolatile(), p2.isRestrict());
|
||||
}
|
||||
final IType target2 = p2.getType();
|
||||
if (isVoidType(target2)) {
|
||||
return addQualifiers(p2, p1.isConst(), p1.isVolatile());
|
||||
return addQualifiers(p2, p1.isConst(), p1.isVolatile(), p1.isRestrict());
|
||||
}
|
||||
|
||||
IType t= mergePointers(target1, target2, true);
|
||||
|
|
|
@ -210,7 +210,7 @@ public class Cost {
|
|||
// Top level cv-qualifiers are compared only for reference bindings.
|
||||
int qdiff= fQualificationAdjustments ^ other.fQualificationAdjustments;
|
||||
if (fReferenceBinding == ReferenceBinding.NO_REF || other.fReferenceBinding == ReferenceBinding.NO_REF)
|
||||
qdiff &= ~3;
|
||||
qdiff &= ~7;
|
||||
|
||||
if (qdiff != 0) {
|
||||
if ((fQualificationAdjustments & qdiff) == 0)
|
||||
|
|
|
@ -168,38 +168,27 @@ public class SemanticUtil {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 0 for no qualifier, 1 for const, 2 for volatile and 3 for const volatile.
|
||||
*/
|
||||
public static CVQualifier getCVQualifier(IType t) {
|
||||
if (t instanceof IQualifierType) {
|
||||
IQualifierType qt= (IQualifierType) t;
|
||||
if (qt.isConst()) {
|
||||
if (qt.isVolatile()) {
|
||||
return cv;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
if (qt.isVolatile())
|
||||
return v;
|
||||
return _;
|
||||
return qt.isConst()
|
||||
? qt.isVolatile() ? CONST_VOLATILE : CONST
|
||||
: qt.isVolatile() ? VOLATILE : NONE;
|
||||
}
|
||||
if (t instanceof IPointerType) {
|
||||
IPointerType pt= (IPointerType) t;
|
||||
if (pt.isConst()) {
|
||||
if (pt.isVolatile()) {
|
||||
return cv;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
if (pt.isVolatile())
|
||||
return v;
|
||||
return _;
|
||||
return pt.isConst()
|
||||
? pt.isVolatile()
|
||||
? pt.isRestrict() ? CONST_VOLATILE_RESTRICT : CONST_VOLATILE
|
||||
: pt.isRestrict() ? CONST_RESTRICT : CONST
|
||||
: pt.isVolatile()
|
||||
? pt.isRestrict() ? VOLATILE_RESTRICT : VOLATILE
|
||||
: pt.isRestrict() ? RESTRICT : NONE;
|
||||
}
|
||||
if (t instanceof IArrayType) {
|
||||
return getCVQualifier(((IArrayType) t).getType());
|
||||
}
|
||||
return _;
|
||||
return NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -263,7 +252,7 @@ public class SemanticUtil {
|
|||
t= getNestedType(qttgt, options);
|
||||
if (t == qttgt)
|
||||
return qt;
|
||||
return addQualifiers(t, qt.isConst(), qt.isVolatile());
|
||||
return addQualifiers(t, qt.isConst(), qt.isVolatile(), false);
|
||||
}
|
||||
} else if (type instanceof IArrayType) {
|
||||
final IArrayType atype= (IArrayType) type;
|
||||
|
@ -365,7 +354,7 @@ public class SemanticUtil {
|
|||
// bug 249085 make sure not to add unnecessary qualifications
|
||||
if (type instanceof IQualifierType) {
|
||||
IQualifierType qt= (IQualifierType) type;
|
||||
return addQualifiers(newNestedType, qt.isConst(), qt.isVolatile());
|
||||
return addQualifiers(newNestedType, qt.isConst(), qt.isVolatile(), false);
|
||||
}
|
||||
|
||||
type = (ITypeContainer) type.clone();
|
||||
|
@ -455,8 +444,12 @@ public class SemanticUtil {
|
|||
return arg;
|
||||
}
|
||||
|
||||
public static IType addQualifiers(IType baseType, boolean cnst, boolean vol) {
|
||||
if (cnst || vol) {
|
||||
public static IType constQualify(IType baseType) {
|
||||
return addQualifiers(baseType, true, false, false);
|
||||
}
|
||||
|
||||
public static IType addQualifiers(IType baseType, boolean cnst, boolean vol, boolean restrict) {
|
||||
if (cnst || vol || restrict) {
|
||||
if (baseType instanceof IQualifierType) {
|
||||
IQualifierType qt= (IQualifierType) baseType;
|
||||
if ((cnst && !qt.isConst()) || (vol && !qt.isVolatile())) {
|
||||
|
@ -465,21 +458,24 @@ public class SemanticUtil {
|
|||
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(), pt.isRestrict());
|
||||
if ((cnst && !pt.isConst()) || (vol && !pt.isVolatile())
|
||||
|| (restrict && !pt.isRestrict())) {
|
||||
return new CPPPointerToMemberType(pt.getType(), pt.getMemberOfClass(),
|
||||
cnst || pt.isConst(), vol || pt.isVolatile(), restrict || pt.isRestrict());
|
||||
}
|
||||
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(), pt.isRestrict());
|
||||
if ((cnst && !pt.isConst()) || (vol && !pt.isVolatile())
|
||||
|| (restrict && !pt.isRestrict())) {
|
||||
return new CPPPointerType(pt.getType(),
|
||||
cnst || pt.isConst(), vol || pt.isVolatile(), restrict || pt.isRestrict());
|
||||
}
|
||||
return baseType;
|
||||
} else if (baseType instanceof IArrayType) {
|
||||
IArrayType at= (IArrayType) baseType;
|
||||
IType nested= at.getType();
|
||||
IType newNested= addQualifiers(nested, cnst, vol);
|
||||
IType newNested= addQualifiers(nested, cnst, vol, restrict);
|
||||
if (newNested != nested && at instanceof ITypeContainer) {
|
||||
return replaceNestedType((ITypeContainer) at, newNested);
|
||||
}
|
||||
|
|
|
@ -697,7 +697,7 @@ public class TemplateArgumentDeduction {
|
|||
} else if (p instanceof IQualifierType) {
|
||||
final CVQualifier cvqP = SemanticUtil.getCVQualifier(p);
|
||||
final CVQualifier cvqA = SemanticUtil.getCVQualifier(a);
|
||||
CVQualifier remaining= CVQualifier._;
|
||||
CVQualifier remaining= CVQualifier.NONE;
|
||||
if (cvqP != cvqA) {
|
||||
if (!allowCVQConversion && !cvqA.isAtLeastAsQualifiedAs(cvqP))
|
||||
return false;
|
||||
|
@ -707,8 +707,8 @@ public class TemplateArgumentDeduction {
|
|||
a = SemanticUtil.getNestedType(a, ALLCVQ);
|
||||
if (p instanceof IQualifierType)
|
||||
return false;
|
||||
if (remaining != CVQualifier._) {
|
||||
a= SemanticUtil.addQualifiers(a, remaining.isConst(), remaining.isVolatile());
|
||||
if (remaining != CVQualifier.NONE) {
|
||||
a= SemanticUtil.addQualifiers(a, remaining.isConst(), remaining.isVolatile(), remaining.isRestrict());
|
||||
}
|
||||
} else if (p instanceof IFunctionType) {
|
||||
if (!(a instanceof IFunctionType))
|
||||
|
|
|
@ -565,7 +565,7 @@ public class ASTManager {
|
|||
if (t2 instanceof IPointerType) {
|
||||
IPointerType a1= (IPointerType) t1;
|
||||
IPointerType a2= (IPointerType) t2;
|
||||
if (a1.isConst() != a2.isConst() || a1.isVolatile() != a2.isVolatile()) {
|
||||
if (a1.isConst() != a2.isConst() || a1.isVolatile() != a2.isVolatile() || a1.isRestrict() != a2.isRestrict()) {
|
||||
return FALSE;
|
||||
}
|
||||
return isSameType(a1.getType(), a2.getType());
|
||||
|
|
Loading…
Add table
Reference in a new issue