mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
CV-Qualifiers and arrays, bug 293982.
This commit is contained in:
parent
75e6f8510f
commit
f43e16c9ea
9 changed files with 254 additions and 117 deletions
|
@ -7655,5 +7655,23 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
assertNotNull(methodTemplate.getType());
|
||||
assertEquals(1, methodTemplate.getParameters().length);
|
||||
}
|
||||
|
||||
// void x(const char (&)[1]) {};
|
||||
//
|
||||
// typedef char Array[12];
|
||||
// typedef const char CArray[12];
|
||||
// void xx(CArray* p);
|
||||
//
|
||||
// template <typename T> void f(T& p);
|
||||
// void test() {
|
||||
// x("");
|
||||
// Array a;
|
||||
// xx(&a);
|
||||
// f("");
|
||||
// }
|
||||
public void testCVQualifiersWithArrays_293982() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,13 +12,15 @@
|
|||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||
|
||||
/**
|
||||
|
@ -106,12 +108,21 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
|||
case lk_string_literal:
|
||||
IType type = new CPPBasicType(getCharType(), 0, this);
|
||||
type = new CPPQualifierType(type, true, false);
|
||||
return new CPPArrayType(type);
|
||||
return new CPPArrayType(type, getStringLiteralSize());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Kind getCharType() {
|
||||
private IValue getStringLiteralSize() {
|
||||
char[] value= getValue();
|
||||
int length= value.length-1;
|
||||
if (value[0] != '"') {
|
||||
length--;
|
||||
}
|
||||
return Value.create(length);
|
||||
}
|
||||
|
||||
private Kind getCharType() {
|
||||
return getValue()[0] == 'L' ? Kind.eWChar : Kind.eChar;
|
||||
}
|
||||
|
||||
|
@ -126,7 +137,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
|||
kind= Kind.eFloat;
|
||||
break;
|
||||
case 'l': case 'L':
|
||||
flags |= ICPPBasicType.IS_LONG;
|
||||
flags |= IBasicType.IS_LONG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -157,13 +168,13 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
|||
|
||||
int flags= 0;
|
||||
if (unsigned) {
|
||||
flags |= ICPPBasicType.IS_UNSIGNED;
|
||||
flags |= IBasicType.IS_UNSIGNED;
|
||||
}
|
||||
|
||||
if (makelong > 1) {
|
||||
flags |= ICPPBasicType.IS_LONG_LONG;
|
||||
flags |= IBasicType.IS_LONG_LONG;
|
||||
} else if (makelong == 1) {
|
||||
flags |= ICPPBasicType.IS_LONG;
|
||||
flags |= IBasicType.IS_LONG;
|
||||
}
|
||||
return new CPPBasicType(Kind.eInt, flags, this);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVQ;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
|
||||
|
@ -229,7 +229,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
|
|||
|
||||
if (op == op_star) {
|
||||
IType type= operand.getExpressionType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF | CVQ);
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
|
||||
if (type instanceof IProblemBinding) {
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -929,7 +929,7 @@ public class CPPSemantics {
|
|||
public int visit(IASTExpression expression) {
|
||||
if (expression instanceof IASTLiteralExpression) {
|
||||
if (((IASTLiteralExpression) expression).getKind() == IASTLiteralExpression.lk_this) {
|
||||
final IType thisType = SemanticUtil.getNestedType(expression.getExpressionType(), TDEF | CVQ | PTR | ARRAY | MPTR | REF);
|
||||
final IType thisType = SemanticUtil.getNestedType(expression.getExpressionType(), TDEF | ALLCVQ | PTR | ARRAY | MPTR | REF);
|
||||
if (thisType instanceof ICPPUnknownBinding || thisType instanceof ICPPTemplateDefinition) {
|
||||
result[0]= true;
|
||||
return PROCESS_ABORT;
|
||||
|
@ -2159,8 +2159,8 @@ public class CPPSemantics {
|
|||
cost = Conversions.checkImplicitConversionSequence(sourceIsLValue, thisType, implicitType, UDCMode.noUDC, true);
|
||||
if (cost.getRank() == Rank.NO_MATCH) {
|
||||
if (CPPTemplates.isDependentType(implicitType) || CPPTemplates.isDependentType(thisType)) {
|
||||
IType s= getNestedType(thisType, TDEF|REF|CVQ);
|
||||
IType t= getNestedType(implicitType, TDEF|REF|CVQ);
|
||||
IType s= getNestedType(thisType, TDEF|REF|CVTYPE);
|
||||
IType t= getNestedType(implicitType, TDEF|REF|CVTYPE);
|
||||
if (Conversions.calculateInheritanceDepth(MAX_INHERITANCE_DEPTH, s, t) >= 0)
|
||||
return null;
|
||||
|
||||
|
@ -2707,7 +2707,7 @@ public class CPPSemantics {
|
|||
args = new IASTExpression[] { exp.getOperand() };
|
||||
|
||||
IType type = exp.getOperand().getExpressionType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF | CVQ);
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
|
||||
if (!isUserDefined(type))
|
||||
return null;
|
||||
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -1479,13 +1483,13 @@ public class CPPTemplates {
|
|||
par= getParameterTypeForDeduction(par, isReferenceType);
|
||||
|
||||
// 14.8.2.1.3
|
||||
int cvPar= Conversions.getCVQualifier(par);
|
||||
int cvArg= Conversions.getCVQualifier(arg);
|
||||
if (cvPar == cvArg || (isReferenceType && (cvArg & ~cvPar) == 0)) {
|
||||
IType pcheck= SemanticUtil.getNestedType(par, SemanticUtil.CVQ | SemanticUtil.PTR_CVQ);
|
||||
CVQualifier cvPar= SemanticUtil.getCVQualifier(par);
|
||||
CVQualifier cvArg= SemanticUtil.getCVQualifier(arg);
|
||||
if (cvPar == cvArg || (isReferenceType && cvPar.isAtLeastAsQualifiedAs(cvArg))) {
|
||||
IType pcheck= SemanticUtil.getNestedType(par, CVTYPE);
|
||||
if (!(pcheck instanceof ICPPTemplateParameter)) {
|
||||
par= pcheck;
|
||||
arg= SemanticUtil.getNestedType(arg, SemanticUtil.CVQ | SemanticUtil.PTR_CVQ);
|
||||
arg= SemanticUtil.getNestedType(arg, CVTYPE);
|
||||
IType argcheck= arg;
|
||||
if (par instanceof IPointerType && arg instanceof IPointerType) {
|
||||
pcheck= ((IPointerType) par).getType();
|
||||
|
@ -1493,11 +1497,11 @@ public class CPPTemplates {
|
|||
if (pcheck instanceof ICPPTemplateParameter) {
|
||||
pcheck= null;
|
||||
} else {
|
||||
cvPar= Conversions.getCVQualifier(pcheck);
|
||||
cvArg= Conversions.getCVQualifier(argcheck);
|
||||
if ((cvArg & ~cvPar) == 0) {
|
||||
pcheck= SemanticUtil.getNestedType(pcheck, SemanticUtil.CVQ);
|
||||
argcheck= SemanticUtil.getNestedType(argcheck, SemanticUtil.CVQ);
|
||||
cvPar= SemanticUtil.getCVQualifier(pcheck);
|
||||
cvArg= SemanticUtil.getCVQualifier(argcheck);
|
||||
if (cvPar.isAtLeastAsQualifiedAs(cvArg)) {
|
||||
pcheck= SemanticUtil.getNestedType(pcheck, CVTYPE);
|
||||
argcheck= SemanticUtil.getNestedType(argcheck, CVTYPE);
|
||||
} else {
|
||||
pcheck= null;
|
||||
}
|
||||
|
@ -1581,7 +1585,7 @@ public class CPPTemplates {
|
|||
if (isReferenceType) {
|
||||
return SemanticUtil.getNestedType(pType, SemanticUtil.REF | SemanticUtil.TDEF);
|
||||
}
|
||||
return SemanticUtil.getNestedType(pType, SemanticUtil.TDEF | SemanticUtil.CVQ | SemanticUtil.PTR_CVQ);
|
||||
return SemanticUtil.getNestedType(pType, SemanticUtil.TDEF | SemanticUtil.ALLCVQ);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1605,7 +1609,7 @@ public class CPPTemplates {
|
|||
} else if (type instanceof IFunctionType) {
|
||||
result = new CPPPointerType(type);
|
||||
} else {
|
||||
result = SemanticUtil.getNestedType(type, SemanticUtil.TDEF | SemanticUtil.CVQ | SemanticUtil.PTR_CVQ );
|
||||
result = SemanticUtil.getNestedType(type, TDEF | ALLCVQ );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -1665,12 +1669,12 @@ public class CPPTemplates {
|
|||
p = pa.getType();
|
||||
a = aa.getType();
|
||||
} else if (p instanceof IQualifierType) {
|
||||
IType uqp = SemanticUtil.getNestedType(p, SemanticUtil.CVQ | SemanticUtil.PTR_CVQ);
|
||||
IType uqa = SemanticUtil.getNestedType(a, SemanticUtil.CVQ | SemanticUtil.PTR_CVQ);
|
||||
IType uqp = SemanticUtil.getNestedType(p, ALLCVQ);
|
||||
IType uqa = SemanticUtil.getNestedType(a, ALLCVQ);
|
||||
if (uqp instanceof ICPPTemplateParameter) {
|
||||
int remaining= Conversions.getCVQualifier(a) & ~Conversions.getCVQualifier(p);
|
||||
if (remaining != 0) {
|
||||
uqa= SemanticUtil.addQualifiers(uqa, (remaining & 1) != 0, (remaining & 2) != 0);
|
||||
CVQualifier remaining= SemanticUtil.getCVQualifier(a).remove(SemanticUtil.getCVQualifier(p));
|
||||
if (remaining != CVQualifier._) {
|
||||
uqa= SemanticUtil.addQualifiers(uqa, remaining.isConst(), remaining.isVolatile());
|
||||
}
|
||||
}
|
||||
a= uqa;
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Markus Schorn - initial API and implementation
|
||||
*******************************************************************************/
|
||||
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);
|
||||
|
||||
final private boolean fConst;
|
||||
final private boolean fVolatile;
|
||||
|
||||
private CVQualifier(boolean c, boolean v) {
|
||||
fConst= c;
|
||||
fVolatile= v;
|
||||
}
|
||||
|
||||
public boolean isConst() {
|
||||
return fConst;
|
||||
}
|
||||
public boolean isVolatile() {
|
||||
return fVolatile;
|
||||
}
|
||||
|
||||
public boolean isAtLeastAsQualifiedAs(CVQualifier other) {
|
||||
return other == _ || this == other || this == cv;
|
||||
}
|
||||
|
||||
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 _;
|
||||
}
|
||||
return _;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier._;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
|
@ -30,6 +31,7 @@ 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.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
|
@ -87,7 +89,7 @@ public class Conversions {
|
|||
source= getNestedType(source, TDEF | REF);
|
||||
}
|
||||
|
||||
IType T2= getNestedType(source, TDEF | REF | CVQ | PTR_CVQ);
|
||||
IType T2= getNestedType(source, TDEF | REF | ALLCVQ);
|
||||
|
||||
// [8.5.3-5] Is an lvalue (but is not a bit-field), and "cv1 T1" is reference-compatible with "cv2 T2,"
|
||||
if (sourceIsLValue) {
|
||||
|
@ -137,7 +139,7 @@ public class Conversions {
|
|||
}
|
||||
|
||||
// [8.5.3-5] Direct binding failed - Otherwise
|
||||
boolean cv1isConst= getCVQualifier(cv1T1) == 1;
|
||||
boolean cv1isConst= getCVQualifier(cv1T1) == CVQualifier.c;
|
||||
if (cv1isConst) {
|
||||
if (!sourceIsLValue && T2 instanceof ICPPClassType) {
|
||||
Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject);
|
||||
|
@ -155,7 +157,7 @@ public class Conversions {
|
|||
|
||||
// 13.3.3.1.7 no temporary object when converting the implicit object parameter
|
||||
if (!isImpliedObject) {
|
||||
IType T1= getNestedType(cv1T1, TDEF | REF | CVQ | PTR_CVQ);
|
||||
IType T1= getNestedType(cv1T1, TDEF | REF | ALLCVQ);
|
||||
boolean illformed= isReferenceRelated(T1, T2) >= 0 && compareQualifications(cv1T1, source) < 0;
|
||||
|
||||
// We must do a non-reference initialization
|
||||
|
@ -168,8 +170,8 @@ public class Conversions {
|
|||
}
|
||||
|
||||
// Non-reference binding
|
||||
IType uqsource= getNestedType(source, TDEF | REF | CVQ);
|
||||
IType uqtarget= getNestedType(target, TDEF | REF | CVQ);
|
||||
IType uqsource= getNestedType(source, TDEF | REF | ALLCVQ);
|
||||
IType uqtarget= getNestedType(target, TDEF | REF | ALLCVQ);
|
||||
|
||||
// [13.3.3.1-6] Derived to base conversion
|
||||
if (uqsource instanceof ICPPClassType && uqtarget instanceof ICPPClassType) {
|
||||
|
@ -209,54 +211,41 @@ public class Conversions {
|
|||
* ordering on cv-qualifiers, so that a type can be said to be more
|
||||
* cv-qualified than another.
|
||||
* @return <ul>
|
||||
* <li>GT 1 if cv1 is more qualified than cv2
|
||||
* <li>EQ 0 if cv1 and cv2 are equally qualified
|
||||
* <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>
|
||||
* @throws DOMException
|
||||
*/
|
||||
private static final int compareQualifications(IType t1, IType t2) throws DOMException {
|
||||
int cv1= getCVQualifier(t1);
|
||||
int cv2= getCVQualifier(t2);
|
||||
CVQualifier cv1= getCVQualifier(t1);
|
||||
CVQualifier cv2= getCVQualifier(t2);
|
||||
|
||||
// same qualifications
|
||||
if (cv1 == cv2)
|
||||
return 0;
|
||||
|
||||
// both are different but not comparable
|
||||
final int diffs= cv1 ^ cv2;
|
||||
if (diffs == 3 && cv1 != 3 && cv2 != 3) {
|
||||
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 cv1 - cv2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 0 for no qualifier, 1 for const, 2 for volatile and 3 for const volatile.
|
||||
*/
|
||||
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.
|
||||
|
@ -269,9 +258,28 @@ 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= SemanticUtil.getNestedType(((IPointerType) t).getType(), TDEF | REF);
|
||||
s= SemanticUtil.getNestedType(((IPointerType) s).getType(), TDEF | REF);
|
||||
if (t instanceof IPointerType) {
|
||||
if (s instanceof IPointerType) {
|
||||
t= SemanticUtil.getNestedType(((IPointerType) t).getType(), TDEF | REF);
|
||||
s= SemanticUtil.getNestedType(((IPointerType) s).getType(), TDEF | REF);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if (t instanceof IArrayType) {
|
||||
if (s instanceof IArrayType) {
|
||||
final IArrayType at = (IArrayType) t;
|
||||
final IArrayType st = (IArrayType) s;
|
||||
final IValue av= at.getSize();
|
||||
final IValue sv= st.getSize();
|
||||
if (av == sv || (av != null && av.equals(sv))) {
|
||||
t= SemanticUtil.getNestedType(at.getType(), TDEF | REF);
|
||||
s= SemanticUtil.getNestedType(st.getType(), TDEF | REF);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (t instanceof IQualifierType)
|
||||
t= SemanticUtil.getNestedType(((IQualifierType) t).getType(), TDEF | REF);
|
||||
|
@ -350,8 +358,8 @@ public class Conversions {
|
|||
* @throws DOMException
|
||||
*/
|
||||
static final Cost checkUserDefinedConversionSequence(boolean sourceIsLValue, IType source, IType target, boolean deferUDC) throws DOMException {
|
||||
IType s= getNestedType(source, TDEF | CVQ | REF);
|
||||
IType t= getNestedType(target, TDEF | CVQ | REF);
|
||||
IType s= getNestedType(source, TDEF | CVTYPE | REF);
|
||||
IType t= getNestedType(target, TDEF | CVTYPE | REF);
|
||||
|
||||
if (!(s instanceof ICPPClassType || t instanceof ICPPClassType)) {
|
||||
return null;
|
||||
|
@ -406,7 +414,7 @@ public class Conversions {
|
|||
for (final ICPPMethod op : ops) {
|
||||
if (op != null && !(op instanceof IProblemBinding)) {
|
||||
final IType returnType = op.getType().getReturnType();
|
||||
final IType uqReturnType= getNestedType(returnType, REF | TDEF | CVQ);
|
||||
final IType uqReturnType= getNestedType(returnType, REF | TDEF | CVTYPE);
|
||||
final int dist = calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, uqReturnType, t);
|
||||
if (dist >= 0) {
|
||||
final ICPPFunctionType ft = op.getType();
|
||||
|
@ -444,7 +452,7 @@ public class Conversions {
|
|||
for (final ICPPMethod op : ops) {
|
||||
if (op != null && !(op instanceof IProblemBinding)) {
|
||||
final IType returnType = op.getType().getReturnType();
|
||||
IType uqReturnType= getNestedType(returnType, TDEF | CVQ | PTR_CVQ);
|
||||
IType uqReturnType= getNestedType(returnType, TDEF | ALLCVQ);
|
||||
Cost c2= checkImplicitConversionSequence(false, uqReturnType, target, UDCMode.noUDC, false);
|
||||
if (c2.getRank() != Rank.NO_MATCH) {
|
||||
ICPPFunctionType ftype = op.getType();
|
||||
|
@ -533,7 +541,7 @@ public class Conversions {
|
|||
// 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, CVQ | PTR_CVQ | TDEF | REF);
|
||||
IType unqualifiedSrcRValue= getNestedType(srcRValue, ALLCVQ | TDEF | REF);
|
||||
if (unqualifiedSrcRValue instanceof ICPPClassType) {
|
||||
if (isCompleteType(unqualifiedSrcRValue)) {
|
||||
source= srcRValue;
|
||||
|
@ -568,7 +576,7 @@ public class Conversions {
|
|||
IASTLiteralExpression lit= (IASTLiteralExpression) val;
|
||||
if (lit.getKind() == IASTLiteralExpression.lk_string_literal) {
|
||||
source= new CPPPointerType(tmp, false, false);
|
||||
cost.setQualificationAdjustment(getCVQualifier(targetPtrTgt) | 1);
|
||||
cost.setQualificationAdjustment(getCVQualifier(targetPtrTgt).isVolatile() ? 2 : 1);
|
||||
cost.setRank(Rank.LVALUE_TRANSFORMATION);
|
||||
isConverted= true;
|
||||
}
|
||||
|
@ -596,9 +604,9 @@ public class Conversions {
|
|||
|
||||
// This should actually be done before the conversion is attempted, see for instance 13.3.3.1-6 and 8.5.14.
|
||||
// However, it does not hurt to do it here either.
|
||||
IType unqualifiedTarget= getNestedType(target, CVQ | PTR_CVQ | TDEF | REF);
|
||||
IType unqualifiedTarget= getNestedType(target, ALLCVQ | TDEF | REF);
|
||||
if (!(unqualifiedTarget instanceof ICPPClassType)) {
|
||||
IType unqualifiedSource= getNestedType(source, CVQ | PTR_CVQ | TDEF | REF);
|
||||
IType unqualifiedSource= getNestedType(source, ALLCVQ | TDEF | REF);
|
||||
if (!(unqualifiedSource instanceof ICPPClassType)) {
|
||||
source= unqualifiedSource;
|
||||
target= unqualifiedTarget;
|
||||
|
@ -659,17 +667,15 @@ public class Conversions {
|
|||
}
|
||||
}
|
||||
|
||||
if (s instanceof IQualifierType || t instanceof IQualifierType) {
|
||||
adjustments <<= 2;
|
||||
int cmp= compareQualifications(t, s); // is t more qualified than s?
|
||||
if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
adjustments |= cmp;
|
||||
s= getNestedType(s, CVQ | TDEF | REF);
|
||||
t= getNestedType(t, CVQ | TDEF | REF);
|
||||
adjustments <<= 2;
|
||||
int cmp= compareQualifications(t, s); // is t more qualified than s?
|
||||
if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
adjustments |= cmp;
|
||||
s= getNestedType(s, ALLCVQ | TDEF | REF);
|
||||
t= getNestedType(t, ALLCVQ | TDEF | REF);
|
||||
|
||||
if (adjustments > 0) {
|
||||
cost.setQualificationAdjustment(adjustments);
|
||||
|
@ -793,12 +799,12 @@ public class Conversions {
|
|||
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(), TDEF | CVQ | REF);
|
||||
IType tgtPtrTgt= getNestedType(tgtPtr.getType(), TDEF | CVTYPE | REF);
|
||||
if (tgtPtrTgt instanceof IBasicType && ((IBasicType) tgtPtrTgt).getKind() == Kind.eVoid) {
|
||||
cost.setRank(Rank.CONVERSION);
|
||||
cost.setInheritanceDistance(Short.MAX_VALUE); // mstodo add distance to last base class
|
||||
int cv= getCVQualifier(srcPtr.getType());
|
||||
cost.source= new CPPPointerType(addQualifiers(CPPSemantics.VOID_TYPE, (cv&1) != 0, (cv&2) != 0));
|
||||
CVQualifier cv= getCVQualifier(srcPtr.getType());
|
||||
cost.source= new CPPPointerType(addQualifiers(CPPSemantics.VOID_TYPE, cv.isConst(), cv.isVolatile()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -807,7 +813,7 @@ public class Conversions {
|
|||
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(), TDEF | CVQ | REF);
|
||||
IType srcPtrTgt= getNestedType(srcPtr.getType(), TDEF | CVTYPE | REF);
|
||||
if (tgtPtrTgt instanceof ICPPClassType && srcPtrTgt instanceof ICPPClassType) {
|
||||
int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, srcPtrTgt, tgtPtrTgt);
|
||||
if (depth == -1) {
|
||||
|
@ -819,8 +825,8 @@ public class Conversions {
|
|||
cost.setRank(Rank.CONVERSION);
|
||||
cost.setInheritanceDistance(depth);
|
||||
}
|
||||
int cv= getCVQualifier(srcPtr.getType());
|
||||
cost.source= new CPPPointerType(addQualifiers(tgtPtrTgt, (cv&1) != 0, (cv&2) != 0));
|
||||
CVQualifier cv= getCVQualifier(srcPtr.getType());
|
||||
cost.source= new CPPPointerType(addQualifiers(tgtPtrTgt, cv.isConst(), cv.isVolatile()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier.*;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
|
@ -59,8 +61,8 @@ public class SemanticUtil {
|
|||
|
||||
public static final int TDEF = 0x01;
|
||||
public static final int REF = 0x02;
|
||||
public static final int CVQ = 0x04;
|
||||
public static final int PTR_CVQ= 0x08;
|
||||
public static final int CVTYPE = 0x04;
|
||||
public static final int ALLCVQ= 0x08;
|
||||
public static final int PTR= 0x10;
|
||||
public static final int MPTR= 0x20;
|
||||
public static final int ARRAY= 0x40;
|
||||
|
@ -164,6 +166,40 @@ public class SemanticUtil {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 0 for no qualifier, 1 for const, 2 for volatile and 3 for const volatile.
|
||||
*/
|
||||
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 _;
|
||||
}
|
||||
if (t instanceof IPointerType) {
|
||||
IPointerType pt= (IPointerType) t;
|
||||
if (pt.isConst()) {
|
||||
if (pt.isVolatile()) {
|
||||
return cv;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
if (pt.isVolatile())
|
||||
return v;
|
||||
return _;
|
||||
}
|
||||
if (t instanceof IArrayType) {
|
||||
return getCVQualifier(((IArrayType) t).getType());
|
||||
}
|
||||
return _;
|
||||
}
|
||||
|
||||
/**
|
||||
* Descends into type containers, stopping at pointer-to-member types if
|
||||
* specified.
|
||||
|
@ -172,7 +208,7 @@ public class SemanticUtil {
|
|||
* @return the deepest type in a type container sequence
|
||||
*/
|
||||
public static IType getUltimateType(IType type, boolean stopAtPointerToMember) {
|
||||
final int options = TDEF | CVQ | PTR | ARRAY | REF;
|
||||
final int options = TDEF | ALLCVQ | PTR | ARRAY | REF;
|
||||
return getNestedType(type, stopAtPointerToMember ? options : (options | MPTR));
|
||||
}
|
||||
|
||||
|
@ -183,25 +219,26 @@ public class SemanticUtil {
|
|||
* @return the ultimate type contained inside the specified type
|
||||
*/
|
||||
public static IType getUltimateTypeUptoPointers(IType type) {
|
||||
return getNestedType(type, TDEF | REF | CVQ);
|
||||
return getNestedType(type, TDEF | REF | CVTYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Descends into typedefs, references, etc. as specified by options.
|
||||
*/
|
||||
public static IType getNestedType(IType type, int options) {
|
||||
boolean tdef= (options & TDEF) != 0;
|
||||
boolean ptrcvq= (options & PTR_CVQ) != 0;
|
||||
boolean ptr= (options & PTR) != 0;
|
||||
boolean mptr= (options & MPTR) != 0;
|
||||
assert !(ptrcvq && (ptr || mptr));
|
||||
final boolean tdef= (options & TDEF) != 0;
|
||||
final boolean ptr= (options & PTR) != 0;
|
||||
final boolean mptr= (options & MPTR) != 0;
|
||||
final boolean allcvq= (options & ALLCVQ) != 0;
|
||||
final boolean cvtype = (options & CVTYPE) != 0;
|
||||
|
||||
while (true) {
|
||||
IType t= null;
|
||||
if (type instanceof IPointerType) {
|
||||
final boolean isMbrPtr = type instanceof ICPPPointerToMemberType;
|
||||
if ((ptr && !isMbrPtr) || (mptr && isMbrPtr)) {
|
||||
t= ((IPointerType) type).getType();
|
||||
} else if (ptrcvq) {
|
||||
} else if (allcvq) {
|
||||
if (type instanceof CPPPointerType) {
|
||||
return ((CPPPointerType) type).stripQualifiers();
|
||||
}
|
||||
|
@ -220,16 +257,24 @@ public class SemanticUtil {
|
|||
t= ((ITypedef) type).getType();
|
||||
} else if (type instanceof IQualifierType) {
|
||||
final IQualifierType qt = (IQualifierType) type;
|
||||
final boolean cvq = (options & CVQ) != 0;
|
||||
if (cvq || tdef) {
|
||||
if (allcvq || cvtype) {
|
||||
t= qt.getType();
|
||||
} else if (tdef) {
|
||||
t= getNestedType(qt.getType(), options);
|
||||
if (!cvq || t instanceof IArrayType || t instanceof ICPPReferenceType) {
|
||||
t= addQualifiers(t, qt.isConst(), qt.isVolatile());
|
||||
}
|
||||
t= addQualifiers(t, qt.isConst(), qt.isVolatile());
|
||||
return t;
|
||||
}
|
||||
} else if ((options & ARRAY) != 0 && type instanceof IArrayType) {
|
||||
t= ((IArrayType) type).getType();
|
||||
} else if (type instanceof IArrayType) {
|
||||
final IArrayType atype= (IArrayType) type;
|
||||
if ((options & ARRAY) != 0) {
|
||||
t= atype.getType();
|
||||
} else if (allcvq) {
|
||||
IType nested= atype.getType();
|
||||
IType newNested= getNestedType(nested, ALLCVQ);
|
||||
if (nested == newNested)
|
||||
return type;
|
||||
return replaceNestedType((ITypeContainer) atype, newNested);
|
||||
}
|
||||
} else if ((options & REF) != 0 && type instanceof ICPPReferenceType) {
|
||||
t= ((ICPPReferenceType) type).getType();
|
||||
}
|
||||
|
@ -397,7 +442,7 @@ public class SemanticUtil {
|
|||
//8.3.5-3
|
||||
//Any cv-qualifier modifying a parameter type is deleted.
|
||||
if (forFunctionType && (t instanceof IQualifierType || t instanceof IPointerType)) {
|
||||
return SemanticUtil.getNestedType(t, TDEF | CVQ | PTR_CVQ);
|
||||
return SemanticUtil.getNestedType(t, TDEF | ALLCVQ);
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ public class AddIncludeOnSelectionAction extends TextEditorAction {
|
|||
if (binding instanceof ICPPVariable) {
|
||||
IType type = ((ICPPVariable) binding).getType();
|
||||
type = SemanticUtil.getNestedType(type,
|
||||
SemanticUtil.CVQ | SemanticUtil.PTR | SemanticUtil.ARRAY | SemanticUtil.REF);
|
||||
SemanticUtil.ALLCVQ | SemanticUtil.PTR | SemanticUtil.ARRAY | SemanticUtil.REF);
|
||||
if (type instanceof IBinding) {
|
||||
binding = (IBinding) type;
|
||||
nameChars = binding.getNameCharArray();
|
||||
|
@ -532,8 +532,7 @@ public class AddIncludeOnSelectionAction extends TextEditorAction {
|
|||
int systemIncludeVotes = 0;
|
||||
String[] ballotBox = new String[includes.length];
|
||||
int k = 0;
|
||||
for (int i = 0; i < includes.length; i++) {
|
||||
IIndexInclude include = includes[i];
|
||||
for (IIndexInclude include : includes) {
|
||||
if (isResolvable(include)) {
|
||||
ballotBox[k++] = include.getFullName();
|
||||
if (include.isSystemInclude()) {
|
||||
|
|
Loading…
Add table
Reference in a new issue