1
0
Fork 0
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:
Markus Schorn 2009-11-03 18:35:47 +00:00
parent 75e6f8510f
commit f43e16c9ea
9 changed files with 254 additions and 117 deletions

View file

@ -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);
}
}

View file

@ -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,11 +108,20 @@ 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 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);
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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 _;
}
}

View file

@ -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,52 +211,39 @@ 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;
}
/**
* 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;
return -1;
}
/**
@ -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) {
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,7 +667,6 @@ 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)) {
@ -667,9 +674,8 @@ public class Conversions {
}
adjustments |= cmp;
s= getNestedType(s, CVQ | TDEF | REF);
t= getNestedType(t, CVQ | TDEF | REF);
}
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;
}

View file

@ -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());
}
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;
}

View file

@ -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()) {