diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 45f6a28419c..3d5562f052f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -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 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); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java index 335dde02365..976a55254fe 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java @@ -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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java index 2e3698f1fdc..e31734b02e6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java @@ -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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 59e4798ab62..19e18f052c5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index f9993145832..e8c126541e6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CVQualifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CVQualifier.java new file mode 100644 index 00000000000..0106034ba6e --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CVQualifier.java @@ -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 _; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index 131cd1f0bd6..68cd7a9f957 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -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 * @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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java index 5e87ce11e6c..814a708bbfa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java @@ -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; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java index 4fd8ebbaec5..ee35e46a8cd 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java @@ -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()) {