diff options
60 files changed, 1058 insertions, 367 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ASTComparer.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ASTComparer.java index 6110daeb3cd..6c329290f07 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ASTComparer.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ASTComparer.java @@ -51,7 +51,8 @@ public class ASTComparer extends Assert { "isReference", "isAssociatedWithLastName", "getNestingLevel", - "getImplicitNames" + "getImplicitNames", + "isLValue" )); 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 cfdd619ff64..82bf53d2ca3 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 @@ -23,6 +23,7 @@ import java.util.Iterator; import junit.framework.TestSuite; import org.eclipse.cdt.core.dom.ast.ASTSignatureUtil; +import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.EScopeKind; import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; @@ -7750,5 +7751,157 @@ public class AST2CPPTests extends AST2BaseTest { final String code= getAboveComment(); parseAndCheckBindings(code, ParserLanguage.CPP); } + + // struct A {}; + // + // void foo(const A&); // #1 + // void foo(A&&); // #2 + // + // A source_rvalue(); + // A& source_ref(); + // A&& source_rvalue_ref(); + // + // const A source_const_rvalue(); + // const A& source_const_ref(); + // const A&& source_const_rvalue_ref(); + // + // int main() { + // A a; + // A& ra = a; + // A&& rra = a; + // const A ca; + // const A& rca = ca; + // const A&& rrca = ca; + // + // foo(a); // #1 + // foo(ra); // #1 + // foo(rra); // #1 + // foo(ca); // #1 + // foo(rca); // #1 + // foo(rrca); // #1 + // foo(source_rvalue()); // #2 + // foo(source_ref()); // #1 + // foo(source_rvalue_ref()); // #2 + // foo(source_const_rvalue()); // #1 + // foo(source_const_ref()); // #1 + // foo(source_const_rvalue_ref()); // #1 + // } + public void testRValueReference_294730() throws Exception { + final String code= getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + IBinding foo1= bh.assertNonProblem("foo(const A&)", 3); + IBinding foo2= bh.assertNonProblem("foo(A&&)", 3); + IBinding b; + b= bh.assertNonProblem("foo(a)", 3); + assertSame(b, foo1); + b= bh.assertNonProblem("foo(ra)", 3); + assertSame(b, foo1); + b= bh.assertNonProblem("foo(rra)", 3); + assertSame(b, foo1); + b= bh.assertNonProblem("foo(ca)", 3); + assertSame(b, foo1); + b= bh.assertNonProblem("foo(rca)", 3); + assertSame(b, foo1); + b= bh.assertNonProblem("foo(rrca)", 3); + assertSame(b, foo1); + b= bh.assertNonProblem("foo(source_rvalue())", 3); + assertSame(b, foo2); + b= bh.assertNonProblem("foo(source_ref())", 3); + assertSame(b, foo1); + b= bh.assertNonProblem("foo(source_rvalue_ref())", 3); + assertSame(b, foo2); + b= bh.assertNonProblem("foo(source_const_rvalue())", 3); + assertSame(b, foo1); + b= bh.assertNonProblem("foo(source_const_ref())", 3); + assertSame(b, foo1); + b= bh.assertNonProblem("foo(source_const_rvalue_ref())", 3); + assertSame(b, foo1); + } + + + // int i; + // typedef int& LRI; + // typedef int&& RRI; + // LRI& r1 = i; // r1 has the type int& + // const LRI& r2 = i; // r2 has the type int& + // const LRI&& r3 = i; // r3 has the type int& + // RRI& r4 = i; // r4 has the type int& + // RRI&& r5 = i; // r5 has the type int&& + public void testRValueReferenceTypedefs_294730() throws Exception { + final String code= getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + IVariable v; + v= bh.assertNonProblem("r1", 2); + assertEquals("int &", ASTTypeUtil.getType(v.getType())); + v= bh.assertNonProblem("r2", 2); + assertEquals("int &", ASTTypeUtil.getType(v.getType())); + v= bh.assertNonProblem("r3", 2); + assertEquals("int &", ASTTypeUtil.getType(v.getType())); + v= bh.assertNonProblem("r4", 2); + assertEquals("int &", ASTTypeUtil.getType(v.getType())); + v= bh.assertNonProblem("r5", 2); + assertEquals("int &&", ASTTypeUtil.getType(v.getType())); + } + + // void dref(double&); + // void drref(double&&); + // void cdref(const double&); + // struct A { }; + // struct B : A { }; + // extern B f(); + // struct X { + // operator B(); + // } x; + // void aref(A&); + // void caref(const A&); + // void carref(const A&&); + // void test() { + // B b; + // double d = 2.0; + // const volatile double cvd = 1; + // int i = 2; + // dref(d); + // cdref(d); + // aref(b); + // caref(b); + // dref(2.0); // error: not an lvalue and reference not const + // dref(i); // error: type mismatch and reference not const + // drref(i); // error: rvalue reference cannot bind to lvalue + // caref(f()); // bound to the A subobject of the B rvalue. + // carref(f()); // same as above + // caref(x); // bound to the A subobject of the result of the conversion + // cdref(2); // rcd2 refers to temporary with value 2.0 + // drref(2); // rcd3 refers to temporary with value 2.0 + // cdref(cvd); // error: type qualifiers dropped + // } + public void testDirectBinding_294730() throws Exception { + final String code= getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + bh.assertNonProblem("dref(d)", 4); + bh.assertNonProblem("cdref(d)", 5); + bh.assertNonProblem("aref(b)", 4); + bh.assertNonProblem("caref(b)", 5); + bh.assertProblem("dref(2.0)", 4); + bh.assertProblem("dref(i)", 4); + bh.assertProblem("drref(i)", 5); + bh.assertNonProblem("caref(f())", 5); + bh.assertNonProblem("carref(f())", 6); + bh.assertNonProblem("caref(x)", 5); + bh.assertNonProblem("cdref(2)", 5); + bh.assertNonProblem("drref(2)", 5); + bh.assertProblem("cdref(cvd)", 5); + } + + // struct S { + // operator int() {return 0;} + // }; + // S s(){return *new S();} + // void test(int) { + // test(s()); + // } + public void testSpecialRuleForImplicitObjectType_294730() throws Exception { + final String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index fba9cb3f342..1daabe62459 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -4296,8 +4296,51 @@ public class AST2TemplateTests extends AST2BaseTest { // int a=1; // a OPASSIGN(>>) 1; // } - public void testTokenPasteShiftROperaotr_261268() throws Exception { + public void testTokenPasteShiftROperator_261268() throws Exception { final String code= getAboveComment(); parseAndCheckBindings(code, ParserLanguage.CPP); } + + // template <class T> class X { + // void f(const T&); + // void g(T&&); + // }; + // X<int&> x1; // X<int&>::f has the parameter type int& + // // X<int&>::g has the parameter type int& + // X<const int&&> x2; // X<const int&&>::f has the parameter type const int& + // // X<const int&&>::g has the parameter type const int&& + public void testRValueReferences_1_294730() throws Exception { + final String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + + ICPPClassType type= bh.assertNonProblem("X<int&>", 7); + ICPPMethod[] ms= type.getMethods(); + int i= ms[0].getName().equals("f") ? 0 : 1; + ICPPMethod m= ms[i]; + assertEquals("int &", ASTTypeUtil.getType(m.getType().getParameterTypes()[0])); + m= ms[1-i]; + assertEquals("int &", ASTTypeUtil.getType(m.getType().getParameterTypes()[0])); + + type= bh.assertNonProblem("X<const int&&>", 14); + ms= type.getMethods(); + i= ms[0].getName().equals("f") ? 0 : 1; + m= ms[i]; + assertEquals("const int &", ASTTypeUtil.getType(m.getType().getParameterTypes()[0])); + m= ms[1-i]; + assertEquals("const int &&", ASTTypeUtil.getType(m.getType().getParameterTypes()[0])); + } + + // template<typename T> int f(T&&); + // void test() { + // int i; + // int j = f(i); // calls f<int&>(i) + // } + public void testRValueReferences_2_294730() throws Exception { + final String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + ICPPTemplateInstance inst= bh.assertNonProblem("f(i)", 1); + assertEquals("<int &>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true)); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOMManager.java index 4faa8648790..874147d85d0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOMManager.java @@ -9,7 +9,6 @@ * Doug Schaefer (QNX) - Initial API and implementation * Markus Schorn (Wind River Systems) *******************************************************************************/ - package org.eclipse.cdt.core.dom; import org.eclipse.cdt.core.model.ICProject; @@ -23,8 +22,9 @@ public interface IPDOMManager { public static final String ID_NO_INDEXER= "org.eclipse.cdt.core.nullindexer"; //$NON-NLS-1$ public static final String ID_FAST_INDEXER= "org.eclipse.cdt.core.fastIndexer"; //$NON-NLS-1$ /** - * @deprecated, the full indexer has been removed. + * @deprecated The full indexer has been removed. */ + @Deprecated public static final String ID_FULL_INDEXER= "org.eclipse.cdt.core.domsourceindexer"; //$NON-NLS-1$ // Getting and setting indexer Ids diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java index 8083c669eb7..d2bfdbf569f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java @@ -350,7 +350,11 @@ public class ASTTypeUtil { result.append(getArgumentListString(inst.getTemplateArguments(), normalize)); } } else if (type instanceof ICPPReferenceType) { - result.append(Keywords.cpAMPER); + if (((ICPPReferenceType) type).isRValueReference()) { + result.append(Keywords.cpAND); + } else { + result.append(Keywords.cpAMPER); + } } else if (type instanceof IEnumeration) { result.append(Keywords.ENUM); result.append(SPACE); @@ -451,6 +455,7 @@ public class ASTTypeUtil { // push all of the types onto the stack int i = 0; IQualifierType cvq= null; + ICPPReferenceType ref= null; while (type != null && ++i < 100) { if (!normalize) { types = (IType[]) ArrayUtil.append(IType.class, types, type); @@ -461,19 +466,38 @@ public class ASTTypeUtil { if (type instanceof ITypedef) { // skip it } else { - if (cvq != null) { - if (type instanceof IQualifierType || type instanceof IPointerType) { - type= SemanticUtil.addQualifiers(type, cvq.isConst(), cvq.isVolatile()); - cvq= null; - } else { - types = (IType[]) ArrayUtil.append(IType.class, types, cvq); + if (type instanceof ICPPReferenceType) { + // reference types ignore cv-qualifiers + cvq=null; + // lvalue references win over rvalue references + if (ref == null || ref.isRValueReference()) { + // delay reference to see if there are more + ref= (ICPPReferenceType) type; } - } - if (type instanceof IQualifierType) { - cvq= (IQualifierType) type; } else { - types = (IType[]) ArrayUtil.append(IType.class, types, type); - } + if (cvq != null) { + // merge cv qualifiers + if (type instanceof IQualifierType || type instanceof IPointerType) { + type= SemanticUtil.addQualifiers(type, cvq.isConst(), cvq.isVolatile()); + cvq= null; + } + } + if (type instanceof IQualifierType) { + // delay cv qualifier to merge it with others + cvq= (IQualifierType) type; + } else { + // no reference, no cv qualifier: output reference and cv-qualifier + if (ref != null) { + types = (IType[]) ArrayUtil.append(IType.class, types, ref); + ref= null; + } + if (cvq != null) { + types = (IType[]) ArrayUtil.append(IType.class, types, cvq); + cvq= null; + } + types = (IType[]) ArrayUtil.append(IType.class, types, type); + } + } } } if (type instanceof ITypeContainer) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTExpression.java index 6939a0d6207..973e23d65ef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTExpression.java @@ -7,6 +7,7 @@ * * Contributors: * Doug Schaefer (IBM) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; @@ -25,6 +26,13 @@ public interface IASTExpression extends IASTNode { public IType getExpressionType(); /** + * Returns whether this expression is an lvalue. LValues are for instance required on the + * left hand side of an assignment expression. + * @since 5.2 + */ + public boolean isLValue(); + + /** * @since 5.1 */ public IASTExpression copy(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTLiteralExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTLiteralExpression.java index 9e74aba10b0..3d40d9391d6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTLiteralExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTLiteralExpression.java @@ -91,15 +91,15 @@ public interface IASTLiteralExpression extends IASTExpression { * @since 5.1 */ public void setValue(char[] value); - + /** - * @deprecated, use {@link #setValue(char[])}, instead. + * @since 5.1 */ - public void setValue(String value); + public IASTLiteralExpression copy(); /** - * @since 5.1 + * @deprecated Replaced by {@link #setValue(char[])}. */ - public IASTLiteralExpression copy(); - + @Deprecated + public void setValue(String value); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTReferenceOperator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTReferenceOperator.java index cc888c778a3..04e1b73eeb3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTReferenceOperator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTReferenceOperator.java @@ -7,6 +7,7 @@ * * Contributors: * Doug Schaefer (IBM) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast.cpp; @@ -21,6 +22,12 @@ import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; public interface ICPPASTReferenceOperator extends IASTPointerOperator { /** + * Returns whether the operator denotes a rvalue reference (e.g. <code>int &&</code>). + * @since 5.2 + */ + public boolean isRValueReference(); + + /** * @since 5.1 */ public ICPPASTReferenceOperator copy(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java index 694ec43a854..c5156e87e45 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java @@ -40,12 +40,6 @@ import org.eclipse.cdt.core.parser.IScanner; public interface ICPPNodeFactory extends INodeFactory { /** - * @deprecated use {@link #newTranslationUnit(IScanner)}, instead. - */ - @Deprecated - public ICPPASTTranslationUnit newTranslationUnit(); - - /** * Creates a new translation unit that cooperates with the given scanner in order * to track macro-expansions and location information. * @scanner the preprocessor the translation unit interacts with. @@ -152,8 +146,12 @@ public interface ICPPNodeFactory extends INodeFactory { public IGPPASTPointer newPointerGPP(); - public ICPPASTReferenceOperator newReferenceOperator(); - + /** + * Creates an lvalue or rvalue reference operator. + * @since 5.2 + */ + public ICPPASTReferenceOperator newReferenceOperator(boolean isRValueReference); + public ICPPASTPointerToMember newPointerToMember(IASTName name); public IGPPASTPointerToMember newPointerToMemberGPP(IASTName name); @@ -183,4 +181,14 @@ public interface ICPPNodeFactory extends INodeFactory { */ public ICPPASTStaticAssertDeclaration newStaticAssertion(IASTExpression condition, ICPPASTLiteralExpression message); + + /** + * @deprecated Replaced by {@link #newReferenceOperator(boolean)}. + */ + @Deprecated public ICPPASTReferenceOperator newReferenceOperator(); + /** + * @deprecated Replaced by {@link #newTranslationUnit(IScanner)}. + */ + @Deprecated + public ICPPASTTranslationUnit newTranslationUnit(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPReferenceType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPReferenceType.java index 195d32317db..5d4d7b4f06f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPReferenceType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPReferenceType.java @@ -7,6 +7,7 @@ * * Contributors: * Andrew Niefer (IBM Corporation) - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast.cpp; @@ -19,7 +20,13 @@ import org.eclipse.cdt.core.dom.ast.IType; public interface ICPPReferenceType extends IType { /** - * get the type that this is a reference of + * Returns the type that this is a reference of */ public IType getType(); + + /** + * Returns whether this is an rvalue reference (e.g: int&&) + * @since 5.2 + */ + public boolean isRValueReference(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java index 33dc8795757..c464d37cac5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java @@ -133,4 +133,8 @@ public abstract class ASTAmbiguousNode extends ASTNode { afterResolution(resolver, bestAlternative); return bestAlternative; } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTypeIdInitializerExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTypeIdInitializerExpression.java index 22f19c5f277..8d3141854ca 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTypeIdInitializerExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTypeIdInitializerExpression.java @@ -86,4 +86,8 @@ public abstract class ASTTypeIdInitializerExpression extends ASTNode implements } return true; } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 0211c0fe93c..2b725d9a2bf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -1152,6 +1152,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { public IType getExpressionType() { throw new UnsupportedOperationException(); } + + public boolean isLValue() { + throw new UnsupportedOperationException(); + } } protected final IASTExpression castExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTArraySubscriptExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTArraySubscriptExpression.java index 83bdceacf17..420e0188cb8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTArraySubscriptExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTArraySubscriptExpression.java @@ -120,4 +120,8 @@ public class CASTArraySubscriptExpression extends ASTNode implements return ((IArrayType)t).getType(); return t; } + + public boolean isLValue() { + return true; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBinaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBinaryExpression.java index 631430e0466..8d926304649 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBinaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBinaryExpression.java @@ -161,4 +161,22 @@ public class CASTBinaryExpression extends ASTNode implements } return t1; } + + public boolean isLValue() { + switch (getOperator()) { + case op_assign: + case op_binaryAndAssign: + case op_binaryOrAssign: + case op_binaryXorAssign: + case op_divideAssign: + case op_minusAssign: + case op_moduloAssign: + case op_multiplyAssign: + case op_plusAssign: + case op_shiftLeftAssign: + case op_shiftRightAssign: + return true; + } + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCastExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCastExpression.java index 703c4581c7d..a75801117ec 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCastExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCastExpression.java @@ -121,4 +121,8 @@ public class CASTCastExpression extends ASTNode implements IASTCastExpression, I IASTTypeId id= getTypeId(); return CVisitor.createType(id.getAbstractDeclarator()); } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCompoundStatementExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCompoundStatementExpression.java index 40d571db67c..77101763296 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCompoundStatementExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCompoundStatementExpression.java @@ -85,5 +85,15 @@ public class CASTCompoundStatementExpression extends ASTNode implements IGNUASTC } return null; } - + + public boolean isLValue() { + IASTCompoundStatement compound = getCompoundStatement(); + IASTStatement[] statements = compound.getStatements(); + if (statements.length > 0) { + IASTStatement st = statements[statements.length - 1]; + if (st instanceof IASTExpressionStatement) + return ((IASTExpressionStatement)st).getExpression().isLValue(); + } + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTConditionalExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTConditionalExpression.java index 947c2760b1d..2851a25c383 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTConditionalExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTConditionalExpression.java @@ -144,4 +144,8 @@ public class CASTConditionalExpression extends ASTNode implements return t3; return t2; } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTExpressionList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTExpressionList.java index 12b74310527..7e49e7f6f0a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTExpressionList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTExpressionList.java @@ -102,4 +102,13 @@ public class CASTExpressionList extends ASTNode implements IASTExpressionList, } return null; } + + public boolean isLValue() { + for (int i = expressions.length-1; i >= 0; i--) { + IASTExpression expr= expressions[i]; + if (expr != null) + return expr.isLValue(); + } + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldReference.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldReference.java index 6bdc76298a9..cc33582510e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldReference.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldReference.java @@ -144,6 +144,14 @@ public class CASTFieldReference extends ASTNode implements IASTFieldReference, I return null; } + + public boolean isLValue() { + if (isPointerDereference()) + return true; + + return getFieldOwner().isLValue(); + } + public IBinding[] findBindings(IASTName n, boolean isPrefix) { return CVisitor.findBindingsForContentAssist(n, isPrefix); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFunctionCallExpression.java index 95a8586e1a4..dc94acc2313 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFunctionCallExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFunctionCallExpression.java @@ -120,4 +120,8 @@ public class CASTFunctionCallExpression extends ASTNode implements return ((IFunctionType) type).getReturnType(); return null; } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTIdExpression.java index 35de0e98c54..67927aad6e7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTIdExpression.java @@ -111,6 +111,10 @@ public class CASTIdExpression extends ASTNode implements IASTIdExpression, IASTC return null; } + public boolean isLValue() { + return true; + } + public IBinding[] findBindings(IASTName n, boolean isPrefix) { IBinding[] bindings = CVisitor.findBindingsForContentAssist(n, isPrefix); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLiteralExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLiteralExpression.java index e7f275d33b5..039be3d0497 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLiteralExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTLiteralExpression.java @@ -99,7 +99,11 @@ public class CASTLiteralExpression extends ASTNode implements IASTLiteralExpress } return null; } - + + public boolean isLValue() { + return getKind() == IASTLiteralExpression.lk_string_literal; + } + private IType classifyTypeOfFloatLiteral() { final char[] lit= getValue(); final int len= lit.length; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTProblemExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTProblemExpression.java index ec1ba3a1b9b..de5442d8015 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTProblemExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTProblemExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2008 IBM Corporation and others. + * Copyright (c) 2004, 2009 IBM Corporation 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 @@ -59,5 +59,8 @@ public class CASTProblemExpression extends CASTProblemOwner implements IASTProbl public IType getExpressionType() { return null; } - + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTypeIdExpression.java index f1791d88cb2..4f8279e42c8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTypeIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTypeIdExpression.java @@ -90,4 +90,8 @@ public class CASTTypeIdExpression extends ASTNode implements IASTTypeIdExpressio } return CVisitor.createType(typeId.getAbstractDeclarator()); } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTUnaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTUnaryExpression.java index ad91cb843fd..a4dc96ef3f8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTUnaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTUnaryExpression.java @@ -121,5 +121,17 @@ public class CASTUnaryExpression extends ASTNode implements IASTUnaryExpression, } return exprType; // return the original } - + + public boolean isLValue() { + switch (getOperator()) { + case op_bracketedPrimary: + return getOperand().isLValue(); + case op_star: + case op_prefixDecr: + case op_prefixIncr: + return true; + default: + return false; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java index 312d2ef238f..3ba0cd9bc45 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java @@ -8,6 +8,7 @@ * Contributors: * John Camelon (IBM) - Initial API and implementation * Mike Kucera (IBM) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -25,15 +26,14 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; -/** - * @author jcamelon - */ public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTArraySubscriptExpression, IASTAmbiguityParent { private IASTExpression subscriptExp; private IASTExpression arrayExpression; + private ICPPFunction overload= UNINITIALIZED_FUNCTION; private IASTImplicitName[] implicitNames = null; @@ -104,7 +104,15 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTAr public ICPPFunction getOverload() { - return CPPSemantics.findOverloadedOperator(this); + if (overload == UNINITIALIZED_FUNCTION) { + overload= null; + IType t = getArrayExpression().getExpressionType(); + t= SemanticUtil.getUltimateTypeUptoPointers(t); + if (t instanceof ICPPClassType && !(t instanceof ICPPUnknownType)) { + overload= CPPSemantics.findOverloadedOperator(this); + } + } + return overload; } @Override @@ -156,28 +164,36 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTAr } public IType getExpressionType() { + ICPPFunction op = getOverload(); + if (op != null) { + try { + return op.getType().getReturnType(); + } catch (DOMException e) { + return e.getProblem(); + } + } IType t = getArrayExpression().getExpressionType(); t= SemanticUtil.getUltimateTypeUptoPointers(t); - try { - if (t instanceof ICPPUnknownType) { - return CPPUnknownClass.createUnnamedInstance(); - } - if (t instanceof ICPPClassType) { - ICPPFunction op = getOverload(); - if (op != null) { - return op.getType().getReturnType(); - } - } - if (t instanceof IPointerType) { - return ((IPointerType) t).getType(); - } - if (t instanceof IArrayType) { - return ((IArrayType) t).getType(); - } - } catch (DOMException e) { - return e.getProblem(); + if (t instanceof ICPPUnknownType) { + return CPPUnknownClass.createUnnamedInstance(); + } + if (t instanceof IPointerType) { + return ((IPointerType) t).getType(); + } + if (t instanceof IArrayType) { + return ((IArrayType) t).getType(); } return null; } - + + public boolean isLValue() { + ICPPFunction op = getOverload(); + if (op != null) { + try { + return CPPVisitor.isLValueReference(op.getType().getReturnType()); + } catch (DOMException e) { + } + } + return true; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java index 2b511f24fa5..19ae917afc9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java @@ -172,6 +172,31 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr return overload = CPPSemantics.findOverloadedOperator(this); } + public boolean isLValue() { + ICPPFunction op = getOverload(); + if (op != null) { + try { + return CPPVisitor.isLValueReference(op.getType().getReturnType()); + } catch (DOMException e) { + } + } + switch (getOperator()) { + case op_assign: + case op_binaryAndAssign: + case op_binaryOrAssign: + case op_binaryXorAssign: + case op_divideAssign: + case op_minusAssign: + case op_moduloAssign: + case op_multiplyAssign: + case op_plusAssign: + case op_shiftLeftAssign: + case op_shiftRightAssign: + return true; + } + return false; + } + private IType createExpressionType() { // Check for overloaded operator. ICPPFunction o= getOverload(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCastExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCastExpression.java index 8800f173483..f6224debc3b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCastExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCastExpression.java @@ -28,6 +28,7 @@ public class CPPASTCastExpression extends ASTNode implements ICPPASTCastExpressi private int op; private IASTExpression operand; private IASTTypeId typeId; + private IType fType; public CPPASTCastExpression() { } @@ -117,6 +118,15 @@ public class CPPASTCastExpression extends ASTNode implements ICPPASTCastExpressi } public IType getExpressionType() { - return CPPVisitor.createType(typeId.getAbstractDeclarator()); + if (fType == null) { + fType= CPPVisitor.createType(typeId.getAbstractDeclarator()); + } + return fType; + } + + public boolean isLValue() { + return CPPVisitor.isLValueReference(getExpressionType()); } + + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatementExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatementExpression.java index 50837be602e..bd4be362270 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatementExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompoundStatementExpression.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * John Camelon (IBM) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -85,4 +86,15 @@ public class CPPASTCompoundStatementExpression extends ASTNode implements IGNUAS } return null; } + + public boolean isLValue() { + IASTCompoundStatement compound = getCompoundStatement(); + IASTStatement[] statements = compound.getStatements(); + if (statements.length > 0) { + IASTStatement st = statements[statements.length - 1]; + if (st instanceof IASTExpressionStatement) + return ((IASTExpressionStatement)st).getExpression().isLValue(); + } + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java index 0710164d351..59c90b28eb5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConditionalExpression.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * John Camelon (IBM) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -144,4 +145,8 @@ public class CPPASTConditionalExpression extends ASTNode implements return t3; return t2; } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java index 94cba9f2f75..c9f17b798ac 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java @@ -7,6 +7,7 @@ * * Contributors: * John Camelon (IBM) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -151,4 +152,8 @@ public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpr public IType getExpressionType() { return CPPSemantics.VOID_TYPE; } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java index c4a4d8752f0..af63b2b445d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java @@ -8,6 +8,7 @@ * Contributors: * John Camelon (IBM) - Initial API and implementation * Mike Kucera (IBM) - implicit names + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -24,6 +25,7 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionList, IASTAmbiguityParent { @@ -172,22 +174,44 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi } } - public IType getExpressionType() { - ICPPFunction[] overloads = getOverloads(); - if(overloads.length > 0) { - ICPPFunction last = overloads[overloads.length-1]; - if(last != null) { - try { + public IType getExpressionType() { + ICPPFunction[] overloads = getOverloads(); + if (overloads.length > 0) { + ICPPFunction last = overloads[overloads.length - 1]; + if (last != null) { + try { return last.getType().getReturnType(); - } catch (DOMException e) { } - } - } - - for (int i = expressions.length-1; i >= 0 ; i--) { - IASTExpression expr= expressions[i]; + } catch (DOMException e) { + } + } + } + + for (int i = expressions.length - 1; i >= 0; i--) { + IASTExpression expr = expressions[i]; if (expr != null) return expr.getExpressionType(); } - return null; - } + return null; + } + + public boolean isLValue() { + ICPPFunction[] overloads = getOverloads(); + if (overloads.length > 0) { + ICPPFunction last = overloads[overloads.length - 1]; + if (last != null) { + try { + return CPPVisitor.isLValueReference(last.getType().getReturnType()); + } catch (DOMException e) { + return false; + } + } + } + + for (int i = expressions.length-1; i >= 0; i--) { + IASTExpression expr= expressions[i]; + if (expr != null) + return expr.isLValue(); + } + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java index 745f878ac91..de83bb6eebb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java @@ -9,9 +9,12 @@ * John Camelon (IBM) - Initial API and implementation * Bryan Wilkinson (QNX) * Mike Kucera (IBM) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; + import java.util.ArrayList; import java.util.List; @@ -31,7 +34,9 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; @@ -205,6 +210,26 @@ public class CPPASTFieldReference extends ASTNode implements return null; } + + public boolean isLValue() { + if (isPointerDereference()) + return true; + + IBinding b= getFieldName().resolveBinding(); + try { + if (b instanceof ICPPMember && ((ICPPMember) b).isStatic()) + return true; + if (b instanceof IVariable) { + if (SemanticUtil.getNestedType(((IVariable) b).getType(), TDEF) instanceof ICPPReferenceType) { + return true; + } + return getFieldOwner().isLValue(); + } + } catch (DOMException e) { + } + return false; + } + public IBinding[] findBindings(IASTName n, boolean isPrefix) { IBinding[] bindings = CPPSemantics.findBindingsForContentAssist(n, isPrefix); List<IBinding> filtered = new ArrayList<IBinding>(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java index f2363a81124..1fc061ced49 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java @@ -8,6 +8,7 @@ * Contributors: * John Camelon (IBM) - Initial API and implementation * Mike Kucera (IBM) - implicit names + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -34,6 +35,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; @@ -199,7 +201,11 @@ public class CPPASTFunctionCallExpression extends ASTNode implements return type; } - private IType computeExpressionType() { + public boolean isLValue() { + return CPPVisitor.isLValueReference(getExpressionType()); + } + + private IType computeExpressionType() { overload= null; try { IType t= null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java index e1fd753713b..3eb92576c84 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java @@ -6,8 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Bryan Wilkinson (QNX) + * John Camelon (IBM) - Initial API and implementation + * Bryan Wilkinson (QNX) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -28,9 +29,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; -/** - * @author jcamelon - */ public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, IASTCompletionContext { private IASTName name; @@ -112,6 +110,14 @@ public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, IAS return null; } + public boolean isLValue() { + IBinding b= getName().resolveBinding(); + if (b instanceof IVariable || b instanceof IFunction) { + return true; + } + return false; + } + public IBinding[] findBindings(IASTName n, boolean isPrefix) { return CPPSemantics.findBindingsForContentAssist(n, isPrefix); } 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 976a55254fe..009be14f7ac 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,6 +12,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; @@ -113,6 +114,10 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx return null; } + public boolean isLValue() { + return getKind() == IASTLiteralExpression.lk_string_literal; + } + private IValue getStringLiteralSize() { char[] value= getValue(); int length= value.length-1; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java index dedb270d20c..5d8d2493a7b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java @@ -256,4 +256,8 @@ public class CPPASTNewExpression extends ASTNode implements } return new CPPPointerType(t); } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTProblemExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTProblemExpression.java index 774c09744a8..a0e061e4eb5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTProblemExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTProblemExpression.java @@ -1,12 +1,12 @@ /******************************************************************************* - * Copyright (c) 2004, 2008 IBM Corporation and others. + * Copyright (c) 2004, 2009 IBM Corporation 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: - * IBM - Initial API and implementation + * John Camelon (IBM) - Initial API and implementation * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -16,9 +16,6 @@ import org.eclipse.cdt.core.dom.ast.IASTProblem; import org.eclipse.cdt.core.dom.ast.IASTProblemExpression; import org.eclipse.cdt.core.dom.ast.IType; -/** - * @author jcamelon - */ public class CPPASTProblemExpression extends CPPASTProblemOwner implements IASTProblemExpression { public CPPASTProblemExpression() { @@ -58,4 +55,8 @@ public class CPPASTProblemExpression extends CPPASTProblemOwner implements IASTP public IType getExpressionType() { return null; } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTReferenceOperator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTReferenceOperator.java index 99676400df9..3eb09471a76 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTReferenceOperator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTReferenceOperator.java @@ -20,11 +20,18 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode; */ public class CPPASTReferenceOperator extends ASTNode implements ICPPASTReferenceOperator { - public CPPASTReferenceOperator() { + private final boolean fIsRValue; + + public CPPASTReferenceOperator(boolean isRValueReference) { + fIsRValue= isRValueReference; } + public boolean isRValueReference() { + return fIsRValue; + } + public CPPASTReferenceOperator copy() { - CPPASTReferenceOperator copy = new CPPASTReferenceOperator(); + CPPASTReferenceOperator copy = new CPPASTReferenceOperator(fIsRValue); copy.setOffsetAndLength(this); return copy; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleTypeConstructorExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleTypeConstructorExpression.java index 66cf4207f70..611ed09ce1a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleTypeConstructorExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleTypeConstructorExpression.java @@ -19,9 +19,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; -/** - * @author jcamelon - */ public class CPPASTSimpleTypeConstructorExpression extends ASTNode implements ICPPASTSimpleTypeConstructorExpression, IASTAmbiguityParent { @@ -100,4 +97,8 @@ public class CPPASTSimpleTypeConstructorExpression extends ASTNode implements public IType getExpressionType() { return new CPPBasicType(CPPBasicType.getKind(st), 0); } + + public boolean isLValue() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdExpression.java index 6e8a6aca413..c9e661699f3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeIdExpression.java @@ -6,21 +6,18 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * John Camelon (IBM) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTTypeId; -import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeIdExpression; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; -/** - * @author jcamelon - */ public class CPPASTTypeIdExpression extends ASTNode implements ICPPASTTypeIdExpression { private int op; @@ -86,11 +83,21 @@ public class CPPASTTypeIdExpression extends ASTNode implements ICPPASTTypeIdExpr public IType getExpressionType() { switch (getOperator()) { - case IASTTypeIdExpression.op_sizeof: + case op_sizeof: return CPPVisitor.get_SIZE_T(this); - case IASTTypeIdExpression.op_typeid: + case op_typeid: return CPPVisitor.get_type_info(this); } return CPPVisitor.createType(getTypeId()); } + + public boolean isLValue() { + switch(getOperator()) { + case op_typeid: + return true; + } + return false; + } + + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypenameExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypenameExpression.java index c9928d34731..625464d0de3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypenameExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypenameExpression.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * John Camelon (IBM) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -20,9 +21,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypenameExpression; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; -/** - * @author jcamelon - */ public class CPPASTTypenameExpression extends ASTNode implements ICPPASTTypenameExpression, IASTAmbiguityParent { @@ -135,4 +133,8 @@ public class CPPASTTypenameExpression extends ASTNode implements } return null; } + + public boolean isLValue() { + return false; + } } 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 e31734b02e6..0ce2d33aa31 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 @@ -271,6 +271,26 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres return origType; } + public boolean isLValue() { + ICPPFunction op = getOverload(); + if (op != null) { + try { + return CPPVisitor.isLValueReference(op.getType().getReturnType()); + } catch (DOMException e) { + } + } + + switch (getOperator()) { + case op_bracketedPrimary: + return getOperand().isLValue(); + case op_star: + case op_prefixDecr: + case op_prefixIncr: + return true; + default: + return false; + } + } private IType findOperatorReturnType() { ICPPFunction operatorFunction = getOverload(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java index 23cc2752389..1ae7fc756a0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java @@ -100,7 +100,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { char[] className = name.getLookupKey(); IParameter[] voidPs = new IParameter[] { new CPPParameter(CPPSemantics.VOID_TYPE, 0) }; - IType pType = new CPPReferenceType(SemanticUtil.addQualifiers(clsType, true, false)); + IType pType = new CPPReferenceType(SemanticUtil.addQualifiers(clsType, true, false), false); IParameter[] ps = new IParameter[] { new CPPParameter(pType, 0) }; int i= 0; @@ -124,7 +124,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { if (!ia.hasUserDeclaredCopyAssignmentOperator()) { //copy assignment operator: A& operator = (const A &) - IType refType = new CPPReferenceType(clsType); + IType refType = new CPPReferenceType(clsType, false); ICPPFunctionType ft= CPPVisitor.createImplicitFunctionType(refType, ps, false, false); ICPPMethod m = new CPPImplicitMethod(this, OverloadableOperator.ASSIGN.toCharArray(), ft, ps); implicits[i++] = m; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java index 71990c1ecab..fd14a698f56 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java @@ -454,7 +454,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { } public ICPPASTReferenceOperator newReferenceOperator() { - return new CPPASTReferenceOperator(); + return new CPPASTReferenceOperator(false); + } + + public ICPPASTReferenceOperator newReferenceOperator(boolean isRValueReference) { + return new CPPASTReferenceOperator(isRValueReference); } public ICPPASTPointerToMember newPointerToMember(IASTName name) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPReferenceType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPReferenceType.java index 783327f5787..b9463a2fb54 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPReferenceType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPReferenceType.java @@ -7,6 +7,7 @@ * * Contributors: * Andrew Niefer (IBM Corporation) - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -20,18 +21,29 @@ import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.core.runtime.CoreException; public class CPPReferenceType implements ICPPReferenceType, ITypeContainer, ISerializableType { - IType type = null; + private IType fType = null; + private boolean fIsRValue; - public CPPReferenceType(IType type) { - this.type = type; + public CPPReferenceType(IType type, boolean isRValue) { + fIsRValue= isRValue; + setType(type); } public IType getType() { - return type; + return fType; } + public boolean isRValueReference() { + return fIsRValue; + } + public void setType(IType t) { - type = t; + if (t instanceof ICPPReferenceType) { + final ICPPReferenceType rt = (ICPPReferenceType) t; + fIsRValue = fIsRValue && rt.isRValueReference(); + t= rt.getType(); + } + fType= t; } public boolean isSameType(IType obj) { @@ -40,11 +52,36 @@ public class CPPReferenceType implements ICPPReferenceType, ITypeContainer, ISer if (obj instanceof ITypedef) return ((ITypedef)obj).isSameType(this); - if (type == null) - return false; - if (obj instanceof ICPPReferenceType) { - return type.isSameType(((ICPPReferenceType) obj).getType()); + final ICPPReferenceType rhs = (ICPPReferenceType) obj; + IType t1= getType(); + IType t2= rhs.getType(); + boolean rv1= isRValueReference(); + boolean rv2= rhs.isRValueReference(); + for(;;) { + if (t1 instanceof ITypedef) { + t1= ((ITypedef) t1).getType(); + } else if (t1 instanceof ICPPReferenceType) { + rv1= rv1 && ((ICPPReferenceType) t1).isRValueReference(); + t1= ((ICPPReferenceType) t1).getType(); + } else { + break; + } + } + for(;;) { + if (t2 instanceof ITypedef) { + t2= ((ITypedef) t2).getType(); + } else if (t2 instanceof ICPPReferenceType) { + rv2= rv2 && ((ICPPReferenceType) t2).isRValueReference(); + t2= ((ICPPReferenceType) t2).getType(); + } else { + break; + } + } + if (t1 == null) + return false; + + return rv1 == rv2 && t1.isSameType(t2); } return false; } @@ -67,12 +104,15 @@ public class CPPReferenceType implements ICPPReferenceType, ITypeContainer, ISer public void marshal(ITypeMarshalBuffer buffer) throws CoreException { int firstByte= ITypeMarshalBuffer.REFERENCE; + if (isRValueReference()) { + firstByte |= ITypeMarshalBuffer.FLAG1; + } buffer.putByte((byte) firstByte); buffer.marshalType(getType()); } public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { IType nested= buffer.unmarshalType(); - return new CPPReferenceType(nested); + return new CPPReferenceType(nested, (firstByte & ITypeMarshalBuffer.FLAG1) != 0); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index ff50c2c4dab..e05a14bc0bc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -2947,17 +2947,16 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { // __attribute__ in-between pointers __attribute_decl_seq(supportAttributeSpecifiers, false); - if (LT(1) == IToken.tAMPER) { -// boolean isRestrict= false; - IToken lastToken= consume(); - final int from= lastToken.getOffset(); + final int lt1 = LT(1); + if (lt1 == IToken.tAMPER || lt1 == IToken.tAND) { + IToken endToken= consume(); + final int offset= endToken.getOffset(); + if (allowCPPRestrict && LT(1) == IToken.t_restrict) { -// isRestrict= true; - lastToken= consume(); + endToken= consume(); } - ICPPASTReferenceOperator refOp = nodeFactory.newReferenceOperator(); - ((ASTNode) refOp).setOffsetAndLength(from, lastToken.getEndOffset()-from); - collection.add(refOp); + ICPPASTReferenceOperator refOp = nodeFactory.newReferenceOperator(lt1 == IToken.tAND); + collection.add(setRange(refOp, offset, endToken.getEndOffset())); return; } 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 d0a9b9561da..5135dfbae12 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 @@ -18,6 +18,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*; import java.util.ArrayList; +import java.util.BitSet; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -1799,7 +1800,7 @@ public class CPPSemantics { return !b1FromIndex ? 1 : -1; } else if (b1FromIndex) { // Both are from index. - if (data.tu != null) { + if (data != null && data.tu != null) { boolean b1Reachable= isReachableFromAst(data.tu, b1); boolean b2Reachable= isReachableFromAst(data.tu, b2); if (b1Reachable != b2Reachable) { @@ -2047,7 +2048,7 @@ public class CPPSemantics { } if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) { - CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.astName); + CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentLValues(), data.astName); } // Reduce our set of candidate functions to only those who have the right number of parameters @@ -2069,7 +2070,6 @@ public class CPPSemantics { return firstViable; // The arguments the function is being called with - final IASTExpression[] args= data.getFunctionArguments(); IType[] argTypes = data.getFunctionArgumentTypes(); if (CPPTemplates.containsDependentType(argTypes)) { if (viableCount == 1) @@ -2086,7 +2086,7 @@ public class CPPSemantics { if (fn == null) continue; - final FunctionCost fnCost= costForFunctionCall(fn, argTypes, args, allowUDC, data); + final FunctionCost fnCost= costForFunctionCall(fn, allowUDC, data); if (fnCost == null) continue; @@ -2137,8 +2137,10 @@ public class CPPSemantics { return bestFnCost.getFunction(); } - private static FunctionCost costForFunctionCall(IFunction fn, IType[] argTypes, IASTExpression[] args, - boolean allowUDC, LookupData data) throws DOMException { + private static FunctionCost costForFunctionCall(IFunction fn, boolean allowUDC, LookupData data) + throws DOMException { + IType[] argTypes = data.getFunctionArgumentTypes(); + BitSet isLValue= data.getFunctionArgumentLValues(); final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType(); if (ftype == null) return null; @@ -2149,9 +2151,7 @@ public class CPPSemantics { implicitType = getImplicitType((ICPPMethod) fn, ftype.isConst(), ftype.isVolatile()); if (data.firstArgIsImpliedMethodArg) { argTypes = ArrayUtil.removeFirst(argTypes); - if (args != null) { - args = ArrayUtil.removeFirst(args); - } + isLValue = isLValue.get(1, isLValue.size()); } } @@ -2175,7 +2175,7 @@ public class CPPSemantics { } else if (thisType.isSameType(implicitType)) { cost = new Cost(thisType, implicitType, Rank.IDENTITY); } else { - cost = Conversions.checkImplicitConversionSequence(sourceIsLValue, thisType, implicitType, UDCMode.noUDC, true); + cost = Conversions.checkImplicitConversionSequence(implicitType, thisType, sourceIsLValue, UDCMode.noUDC, true); if (cost.getRank() == Rank.NO_MATCH) { if (CPPTemplates.isDependentType(implicitType) || CPPTemplates.isDependentType(thisType)) { IType s= getNestedType(thisType, TDEF|REF|CVTYPE); @@ -2195,12 +2195,11 @@ public class CPPSemantics { final UDCMode udc = allowUDC ? UDCMode.deferUDC : UDCMode.noUDC; for (int j = 0; j < sourceLen; j++) { - final IType argType= argTypes[j]; + final IType argType= SemanticUtil.getNestedType(argTypes[j], TDEF | REF); if (argType == null) return null; - final IASTExpression arg= args != null && j < args.length ? args[j] : null; - final boolean sourceIsLValue = arg != null && !CPPVisitor.isRValue(arg); + final boolean sourceIsLValue = isLValue.get(j); IType paramType; if (j < paramTypes.length) { @@ -2218,7 +2217,7 @@ public class CPPSemantics { } else { if (CPPTemplates.isDependentType(paramType)) return CONTAINS_DEPENDENT_TYPES; - cost = Conversions.checkImplicitConversionSequence(sourceIsLValue, argType, paramType, udc, false); + cost = Conversions.checkImplicitConversionSequence(paramType, argType, sourceIsLValue, udc, false); } if (cost.getRank() == Rank.NO_MATCH) return null; @@ -2236,7 +2235,7 @@ public class CPPSemantics { owner= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) owner); } implicitType= SemanticUtil.addQualifiers(owner, isConst, isVolatile); - implicitType= new CPPReferenceType(implicitType); + implicitType= new CPPReferenceType(implicitType, false); return implicitType; } 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 d659b80e527..dd0bd9c3224 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,11 +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 static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*; import java.util.ArrayList; +import java.util.BitSet; import java.util.Collections; import java.util.List; @@ -122,6 +121,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodTemplateSpecialization; 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; @@ -634,7 +634,7 @@ public class CPPTemplates { * 14.8.2.1 */ static private ICPPTemplateArgument[] deduceTemplateFunctionArguments(ICPPFunctionTemplate template, - ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, CPPTemplateParameterMap map) throws DOMException { + ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, BitSet argIsLValue, CPPTemplateParameterMap map) throws DOMException { final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters(); final int length = tmplParams.length; if (tmplArgs.length > length) @@ -654,7 +654,7 @@ public class CPPTemplates { result[i]= tmplArg; } - if (!deduceTemplateParameterMapFromFunctionParameters(template, fnArgs, map, false)) + if (!deduceTemplateParameterMapFromFunctionParameters(template, fnArgs, argIsLValue, map, false)) return null; for (int i = 0; i < length; i++) { @@ -1360,7 +1360,7 @@ public class CPPTemplates { return result; } - static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] fnArgs, IASTName name) { + static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] fnArgs, BitSet argIsLValue, IASTName name) { boolean requireTemplate= false; if (name != null) { if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) { @@ -1399,7 +1399,7 @@ public class CPPTemplates { } CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length); try { - ICPPTemplateArgument[] args= deduceTemplateFunctionArguments(template, templateArguments, fnArgs, map); + ICPPTemplateArgument[] args= deduceTemplateFunctionArguments(template, templateArguments, fnArgs, argIsLValue, map); if (args != null) { IBinding instance= instantiateFunctionTemplate(template, args); if (instance instanceof IFunction) { @@ -1458,7 +1458,7 @@ public class CPPTemplates { * returns <code>false</code> if there is no mapping. */ private static boolean deduceTemplateParameterMapFromFunctionParameters(ICPPFunctionTemplate template, - IType[] fnArgs, CPPTemplateParameterMap map, boolean checkExactMatch) throws DOMException { + IType[] fnArgs, BitSet argIsLValue, CPPTemplateParameterMap map, boolean checkExactMatch) throws DOMException { try { IType[] fnPars = template.getType().getParameterTypes(); if (fnPars.length == 0) @@ -1478,12 +1478,24 @@ public class CPPTemplates { IType par= instPars[j]; boolean isDependentPar= isDependentType(par); if (checkExactMatch || isDependentPar) { + boolean isReferenceTypeParameter= false; + IType arg = fnArgs[j]; par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF); // adjustParameterType preserves typedefs // 14.8.2.1-2 - final boolean isReferenceTypeParameter = par instanceof ICPPReferenceType; - IType arg= getArgumentTypeForDeduction(fnArgs[j], isReferenceTypeParameter); - if (isReferenceTypeParameter) + if (par instanceof ICPPReferenceType) { + // If P is an rvalue reference to a cv-unqualified template parameter and the argument is an + // lvalue, the type A& “lvalue reference to A” is used in place of A for type deduction. + isReferenceTypeParameter= true; + final ICPPReferenceType refPar = (ICPPReferenceType) par; + if (refPar.isRValueReference() && refPar.getType() instanceof ICPPTemplateParameter && argIsLValue.get(j)) { + arg= new CPPReferenceType(getSimplifiedType(arg), false); + } else { + arg= getArgumentTypeForDeduction(arg, true); + } par= SemanticUtil.getNestedType(par, SemanticUtil.REF | SemanticUtil.TDEF); + } else { + arg= getArgumentTypeForDeduction(arg, false); + } if (!checkExactMatch) { // 14.8.2.1-3 @@ -1841,7 +1853,7 @@ public class CPPTemplates { CPPTemplateParameterMap map= new CPPTemplateParameterMap(2); final IType[] transferredParameterTypes = ((ICPPFunction) transferredTemplate).getType().getParameterTypes(); - if (!deduceTemplateParameterMapFromFunctionParameters(f2, transferredParameterTypes, map, true)) + if (!deduceTemplateParameterMapFromFunctionParameters(f2, transferredParameterTypes, new BitSet(), map, true)) return false; final ICPPTemplateParameter[] tmplParams = f2.getTemplateParameters(); @@ -2078,7 +2090,7 @@ public class CPPTemplates { } else if (paramType instanceof IArrayType) { paramType = new CPPPointerType(((IArrayType) paramType).getType()); } - Cost cost = Conversions.checkImplicitConversionSequence(true, arg, paramType, UDCMode.noUDC, false); + Cost cost = Conversions.checkImplicitConversionSequence(paramType, arg, true, UDCMode.noUDC, false); return cost != null && cost.getRank() != Rank.NO_MATCH; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java index 40639690116..d5425756a40 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java @@ -46,7 +46,7 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags { @Override protected int rwAssignmentToType(IType type, int indirection) { if (indirection == 0) { - if (!(type instanceof ICPPReferenceType)) { + if (!(type instanceof ICPPReferenceType) || ((ICPPReferenceType) type).isRValueReference()) { return READ; } type= ((ICPPReferenceType) type).getType(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 4274d0a8d2c..a0f33b20967 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -44,7 +44,6 @@ import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression; import org.eclipse.cdt.core.dom.ast.IASTInitializerList; import org.eclipse.cdt.core.dom.ast.IASTLabelStatement; -import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTNode; @@ -1617,7 +1616,8 @@ public class CPPVisitor extends ASTQueries { } else if (ptrOp instanceof IASTPointer) { type = new CPPPointerType(type, (IASTPointer) ptrOp); } else if (ptrOp instanceof ICPPASTReferenceOperator) { - type = new CPPReferenceType(type); + final ICPPASTReferenceOperator refOp = (ICPPASTReferenceOperator) ptrOp; + type = new CPPReferenceType(type, refOp.isRValueReference()); } } return type; @@ -1976,37 +1976,9 @@ public class CPPVisitor extends ASTQueries { return false; } - /** - * [3.10] Lvalues and Rvalues - * @param exp - * @return whether the specified expression is an rvalue - */ - static boolean isRValue(IASTExpression exp) { - if (exp instanceof IASTUnaryExpression) { - IASTUnaryExpression ue= (IASTUnaryExpression) exp; - if (ue.getOperator() == IASTUnaryExpression.op_amper) { - return true; - } - } - if (exp instanceof IASTLiteralExpression) - return true; - if (exp instanceof IASTFunctionCallExpression) { - try { - IASTFunctionCallExpression fc= (IASTFunctionCallExpression) exp; - IASTExpression fne= fc.getFunctionNameExpression(); - if (fne instanceof IASTIdExpression) { - IASTIdExpression ide= (IASTIdExpression) fne; - IBinding b= ide.getName().resolveBinding(); - if (b instanceof IFunction) { - IFunctionType tp= ((IFunction) b).getType(); - return !(tp.getReturnType() instanceof ICPPReferenceType); - } - } - } catch (DOMException de) { - // fall-through - } - } - return false; + public static boolean isLValueReference(IType t) { + t= SemanticUtil.getNestedType(t, TDEF); + return t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference(); } /** 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 492290acb1c..f84916440a5 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 @@ -17,7 +17,8 @@ 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; +import java.util.BitSet; + import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; @@ -43,7 +44,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion; import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; @@ -51,126 +51,166 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank; -import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; -import org.eclipse.core.runtime.CoreException; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.ReferenceBinding; /** * Routines for calculating the cost of conversions. */ public class Conversions { enum UDCMode {allowUDC, noUDC, deferUDC} - + + private static final BitSet RVBITSET = new BitSet(); + private static final BitSet LVBITSET = new BitSet(); + static { + LVBITSET.set(0, true); + } /** * Computes the cost of an implicit conversion sequence * [over.best.ics] 13.3.3.1 - * @param sourceIsLValue whether the source type is an lvalue - * @param source the source (argument) type * @param target the target (parameter) type - * @param isImpliedObject - * + * @param exprType the source (argument) type + * @param exprIsLValue whether the source type is an lvalue + * @param isImpliedObjectType * @return the cost of converting from source to target * @throws DOMException */ - public static Cost checkImplicitConversionSequence(boolean sourceIsLValue, IType source, - IType target, UDCMode udc, boolean isImpliedObject) throws DOMException { - if (isImpliedObject) { + public static Cost checkImplicitConversionSequence(IType target, IType exprType, + boolean exprIsLValue, UDCMode udc, boolean isImpliedObjectType) throws DOMException { + if (isImpliedObjectType) { udc= UDCMode.noUDC; } target= getNestedType(target, TDEF); - source= getNestedType(source, TDEF); + exprType= getNestedType(exprType, TDEF | REF); if (target instanceof ICPPReferenceType) { // [8.5.3-5] initialization of a reference - IType cv1T1= getNestedType(target, TDEF | REF); - - if (source instanceof ICPPReferenceType) { - sourceIsLValue= true; - source= getNestedType(source, TDEF | REF); + final boolean isLValueRef= !((ICPPReferenceType) target).isRValueReference(); + final IType cv1T1= getNestedType(target, TDEF | REF); + final IType T1= getNestedType(cv1T1, TDEF | REF | ALLCVQ); + final IType cv2T2= exprType; + final IType T2= getNestedType(cv2T2, TDEF | REF | ALLCVQ); + + final boolean isImplicitWithoutRefQualifier = isImpliedObjectType; // mstodo need to pass this information to here + ReferenceBinding refBindingType= ReferenceBinding.OTHER; + if (!isImplicitWithoutRefQualifier) { + if (isLValueRef) { + refBindingType= ReferenceBinding.LVALUE_REF; + } else if (exprIsLValue) { + refBindingType= ReferenceBinding.RVALUE_REF_BINDS_RVALUE; + } } - - 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) { - Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject); - if (cost != null) { - // [8.5.3-5] this is a direct reference binding - // [13.3.3.1.4-1] direct binding has either identity or conversion rank. - if (cost.getInheritanceDistance() > 0) { - cost.setRank(Rank.CONVERSION); - } - return cost; - } - } - if (T2 instanceof ICPPClassType && udc != UDCMode.noUDC) { - // Or has a class type (i.e., T2 is a class type) and can be implicitly converted to - // an lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible with "cv3 T3" 92) - // (this conversion is selected by enumerating the applicable conversion functions - // (13.3.1.6) and choosing the best one through overload resolution (13.3)). - ICPPMethod[] fcns= SemanticUtil.getConversionOperators((ICPPClassType) T2); - Cost operatorCost= null; - boolean ambiguousConversionOperator= false; - if (fcns.length > 0 && !(fcns[0] instanceof IProblemBinding)) { - for (final ICPPMethod op : fcns) { - IType newSource= op.getType().getReturnType(); - if (newSource instanceof ICPPReferenceType) { // require an lvalue - IType cvT2= getNestedType(newSource, TDEF | REF); - Cost cost2= isReferenceCompatible(cv1T1, cvT2, false); - if (cost2 != null) { - int cmp= cost2.compareTo(operatorCost); - if (cmp <= 0) { - ambiguousConversionOperator= cmp == 0; - operatorCost= cost2; - operatorCost.setUserDefinedConversion(op); - } - } - } - } + // If the reference is an lvalue reference and ... + if (isLValueRef) { + // ... the initializer expression is an lvalue (but is not a bit field) + // [for overload resolution bit-fields are treated the same, error if selected as best match] + if (exprIsLValue) { + // ... and "cv1 T1" is reference-compatible with "cv2 T2" + Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObjectType); + if (cost != null) { + // [13.3.3.1.4-1] direct binding has either identity or conversion rank. + if (cost.getInheritanceDistance() > 0) { + cost.setRank(Rank.CONVERSION); + } + cost.setReferenceBinding(refBindingType); + return cost; + } } - - if (operatorCost != null && !ambiguousConversionOperator) { - if (isImpliedObject) { - operatorCost.setInheritanceDistance(0); + // ... or has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be + // implicitly converted to an lvalue of type “cv3 T3,” where “cv1 T1” is reference-compatible with + // “cv3 T3” (this conversion is selected by enumerating the applicable conversion functions (13.3.1.6) + // and choosing the best one through overload resolution (13.3)), + if (T2 instanceof ICPPClassType && udc != UDCMode.noUDC && isReferenceRelated(T1, T2) < 0) { + Cost cost= conversionFuncForDirectReference(cv1T1, cv2T2, T2, true); + if (cost != null) { + cost.setReferenceBinding(refBindingType); + return cost; } - return operatorCost; } } + + // Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 + // shall be const), or the reference shall be an rvalue reference and the initializer expression + // shall be an rvalue. + boolean ok; + if (isLValueRef) { + // mstodo + // Special rule for implicit object type, 13.3.1-5: + // Even if the implicit object type is not const-qualified, an rvalue temporary can + // be bound to the parameter as long as in all other respects .... + // + final CVQualifier cvq = getCVQualifier(cv1T1); + ok = cvq == CVQualifier.c; + } else { + ok= !exprIsLValue; + } + if (!ok) { + return new Cost(exprType, cv1T1, Rank.NO_MATCH); + } + + // If T1 and T2 are class types and ... + if (T1 instanceof ICPPClassType && T2 instanceof ICPPClassType) { + // ... the initializer expression is an rvalue and “cv1 T1” is reference-compatible with “cv2 T2” + if (!exprIsLValue) { + Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObjectType); + if (cost != null) { + // [13.3.3.1.4-1] direct binding has either identity or conversion rank. + if (cost.getInheritanceDistance() > 0) { + cost.setRank(Rank.CONVERSION); + } + cost.setReferenceBinding(refBindingType); + return cost; + } + } - // [8.5.3-5] Direct binding failed - Otherwise - boolean cv1isConst= getCVQualifier(cv1T1) == CVQualifier.c; - if (cv1isConst) { - if (!sourceIsLValue && T2 instanceof ICPPClassType) { - Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject); - if (cost != null) + // or T1 is not reference-related to T2 and the initializer expression can be implicitly + // converted to an rvalue of type “cv3 T3” (this conversion is selected by enumerating the + // applicable conversion functions (13.3.1.6) and choosing the best one through overload + // resolution (13.3)), then the reference is bound to the initializer expression rvalue in the + // first case and to the object that is the result of the conversion in the second case (or, + // in either case, to the appropriate base class subobject of the object). + if (udc != UDCMode.noUDC && isReferenceRelated(T1, T2) < 0) { + Cost cost= conversionFuncForDirectReference(cv1T1, cv2T2, T2, false); + if (cost != null) { + cost.setReferenceBinding(refBindingType); return cost; + } } + } - // 5 - Otherwise - // Otherwise, a temporary of type "cv1 T1" is created and initialized from - // the initializer expression using the rules for a non-reference copy - // initialization (8.5). The reference is then bound to the temporary. + // If the initializer expression is an rvalue, with T2 an array type, and “cv1 T1” is + // reference-compatible with “cv2 T2,” the reference is bound to the object represented by the + // rvalue (see 3.10). + if (!exprIsLValue && T2 instanceof IArrayType) { + Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObjectType); + if (cost != null) { + cost.setReferenceBinding(refBindingType); + return cost; + } + } - // If T1 is reference-related to T2, cv1 must be the same cv-qualification as, - // or greater cv-qualification than, cv2; otherwise, the program is ill-formed. + // — Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer + // expression using the rules for a non-reference copy initialization (8.5). The reference is then + // bound to the temporary. If T1 is reference-related to T2, cv1 must be the same cv-qualification + // as, or greater cv-qualification than, cv2; otherwise, the program is ill-formed. - // 13.3.3.1.7 no temporary object when converting the implicit object parameter - if (!isImpliedObject) { - IType T1= getNestedType(cv1T1, TDEF | REF | ALLCVQ); - boolean illformed= isReferenceRelated(T1, T2) >= 0 && compareQualifications(cv1T1, source) < 0; - - // We must do a non-reference initialization - if (!illformed) { - return nonReferenceConversion(sourceIsLValue, source, T1, udc, isImpliedObject); + // 13.3.3.1.7 no temporary object when converting the implicit object parameter + if (!isImpliedObjectType) { + if (isReferenceRelated(T1, T2) < 0 || compareQualifications(cv1T1, cv2T2) >= 0) { + Cost cost= nonReferenceConversion(exprIsLValue, cv2T2, T1, udc, false); + if (!isImplicitWithoutRefQualifier) { + cost.setReferenceBinding(isLValueRef ? ReferenceBinding.LVALUE_REF : ReferenceBinding.RVALUE_REF_BINDS_RVALUE); } + return cost; } } - return new Cost(source, cv1T1, Rank.NO_MATCH); + return new Cost(exprType, cv1T1, Rank.NO_MATCH); } // Non-reference binding - IType uqsource= getNestedType(source, TDEF | REF | ALLCVQ); + IType uqsource= getNestedType(exprType, TDEF | REF | ALLCVQ); IType uqtarget= getNestedType(target, TDEF | REF | ALLCVQ); // [13.3.3.1-6] Derived to base conversion @@ -186,13 +226,53 @@ public class Conversions { } } - return nonReferenceConversion(sourceIsLValue, source, uqtarget, udc, isImpliedObject); + return nonReferenceConversion(exprIsLValue, exprType, uqtarget, udc, isImpliedObjectType); + } + + /** + * 0x: 13.3.1.6 Initialization by conversion function for direct reference binding + */ + private static Cost conversionFuncForDirectReference(final IType cv1T1, final IType cv2T2, final IType T2, boolean forLValue) + throws DOMException { + ICPPMethod[] fcns= SemanticUtil.getConversionOperators((ICPPClassType) T2); + Cost operatorCost= null; + FunctionCost bestUdcCost= null; + boolean ambiguousConversionOperator= false; + if (fcns.length > 0 && !(fcns[0] instanceof IProblemBinding)) { + for (final ICPPMethod op : fcns) { + final ICPPFunctionType ft = op.getType(); + IType convertedType= ft.getReturnType(); + final boolean isLValue = CPPVisitor.isLValueReference(convertedType); + if (isLValue == forLValue) { // require an lvalue or rvalue + IType implicitObjectType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile()); + Cost udcCost= isReferenceCompatible(getNestedType(implicitObjectType, TDEF | REF), cv2T2, true); // expression type to implicit object type + if (udcCost != null) { + FunctionCost udcFuncCost= new FunctionCost(op, udcCost); + int cmp= udcFuncCost.compareTo(null, bestUdcCost); + if (cmp <= 0) { + Cost cost= isReferenceCompatible(cv1T1, getNestedType(convertedType, TDEF | REF), false); // converted to target + if (cost != null) { + bestUdcCost= udcFuncCost; + ambiguousConversionOperator= cmp == 0; + operatorCost= cost; + operatorCost.setUserDefinedConversion(op); + } + } + } + } + } + } + + if (operatorCost != null && !ambiguousConversionOperator) { + return operatorCost; + } + return null; } private static Cost nonReferenceConversion(boolean sourceIsLValue, IType source, IType target, UDCMode udc, boolean isImpliedObject) throws DOMException { // [13.3.3.1-6] Subsume cv-qualifications IType uqSource= SemanticUtil.getNestedType(source, TDEF | ALLCVQ); - Cost cost= checkStandardConversionSequence(uqSource, target, isImpliedObject); + Cost cost= checkStandardConversionSequence(uqSource, sourceIsLValue, target, isImpliedObject); if (cost.getRank() != Rank.NO_MATCH || udc == UDCMode.noUDC) return cost; @@ -327,10 +407,10 @@ public class Conversions { * base conversion does not cause any costs. * @throws DOMException */ - private static final Cost checkStandardConversionSequence(IType source, IType target, + private static final Cost checkStandardConversionSequence(IType source, boolean isLValue, IType target, boolean isImplicitThis) throws DOMException { final Cost cost= new Cost(source, target, Rank.IDENTITY); - if (lvalue_to_rvalue(cost)) + if (lvalue_to_rvalue(cost, isLValue)) return cost; if (promotion(cost)) @@ -370,25 +450,25 @@ public class Conversions { // 13.3.1.4 Copy initialization of class by user-defined conversion if (t instanceof ICPPClassType) { - Cost cost1= null; + FunctionCost cost1= null; Cost cost2= null; ICPPConstructor[] ctors= ((ICPPClassType) t).getConstructors(); - CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, null); + CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, sourceIsLValue ? LVBITSET : RVBITSET, null); for (ICPPConstructor ctor : ctors) { if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) { final ICPPFunctionType ft = ctor.getType(); final IType[] ptypes = ft.getParameterTypes(); - Cost c1; + FunctionCost c1; if (ptypes.length == 0) { if (ctor.takesVarArgs()) { - c1= new Cost(source, null, Rank.ELLIPSIS_CONVERSION); + c1= new FunctionCost(ctor, new Cost(source, null, Rank.ELLIPSIS_CONVERSION)); } else { continue; } } else { IType ptype= ptypes[0]; - // We don't need to check the implicit conversion sequence it the type is void + // We don't need to check the implicit conversion sequence if the type is void if (ptype instanceof ICPPBasicType && ((ICPPBasicType) ptype).getKind() == Kind.eVoid) continue; if (ptypes.length > 1) { @@ -397,9 +477,9 @@ public class Conversions { continue; } - c1= checkImplicitConversionSequence(sourceIsLValue, source, ptype, UDCMode.noUDC, false); + c1= new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, sourceIsLValue, UDCMode.noUDC, false)); } - int cmp= c1.compareTo(cost1); + int cmp= c1.compareTo(null, cost1); if (cmp <= 0) { cost1= c1; cost2= new Cost(t, t, Rank.IDENTITY); @@ -421,25 +501,28 @@ public class Conversions { if (dist >= 0) { final ICPPFunctionType ft = op.getType(); IType implicitType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile()); - Cost c1= checkImplicitConversionSequence(sourceIsLValue, source, implicitType, UDCMode.noUDC, false); - int cmp= c1.compareTo(cost1); - if (cmp <= 0) { - cost1= c1; - cost2= new Cost(t, t, Rank.IDENTITY); - if (dist > 0) { - cost2.setInheritanceDistance(dist); - cost2.setRank(Rank.CONVERSION); - } - cost2.setUserDefinedConversion(op); - if (cmp == 0) { - cost2.setAmbiguousUDC(true); + final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true); + if (udcCost != null) { + FunctionCost c1= new FunctionCost(op, udcCost); + int cmp= c1.compareTo(null, cost1); + if (cmp <= 0) { + cost1= c1; + cost2= new Cost(t, t, Rank.IDENTITY); + if (dist > 0) { + cost2.setInheritanceDistance(dist); + cost2.setRank(Rank.CONVERSION); + } + cost2.setUserDefinedConversion(op); + if (cmp == 0) { + cost2.setAmbiguousUDC(true); + } } } } } } } - if (cost1 == null || cost1.getRank() == Rank.NO_MATCH) + if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH) return null; return cost2; @@ -449,30 +532,35 @@ public class Conversions { if (s instanceof ICPPClassType) { ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s); CPPTemplates.instantiateConversionTemplates(ops, target); - Cost cost1= null; + FunctionCost cost1= null; Cost cost2= null; for (final ICPPMethod op : ops) { if (op != null && !(op instanceof IProblemBinding)) { final IType returnType = op.getType().getReturnType(); IType uqReturnType= getNestedType(returnType, TDEF | ALLCVQ); - Cost c2= checkImplicitConversionSequence(false, uqReturnType, target, UDCMode.noUDC, false); + boolean isLValue = uqReturnType instanceof ICPPReferenceType + && !((ICPPReferenceType) uqReturnType).isRValueReference(); + Cost c2= checkImplicitConversionSequence(target, uqReturnType, isLValue, UDCMode.noUDC, false); if (c2.getRank() != Rank.NO_MATCH) { ICPPFunctionType ftype = op.getType(); IType implicitType= CPPSemantics.getImplicitType(op, ftype.isConst(), ftype.isVolatile()); - Cost c1= checkImplicitConversionSequence(sourceIsLValue, source, implicitType, UDCMode.noUDC, false); - int cmp= c1.compareTo(cost1); - if (cmp <= 0) { - cost1= c1; - cost2= c2; - cost2.setUserDefinedConversion(op); - if (cmp == 0) { - cost2.setAmbiguousUDC(true); + final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true); + if (udcCost != null) { + FunctionCost c1= new FunctionCost(op, udcCost); + int cmp= c1.compareTo(null, cost1); + if (cmp <= 0) { + cost1= c1; + cost2= c2; + cost2.setUserDefinedConversion(op); + if (cmp == 0) { + cost2.setAmbiguousUDC(true); + } } } } } } - if (cost1 == null || cost1.getRank() == Rank.NO_MATCH) + if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH) return null; return cost2; @@ -511,7 +599,6 @@ public class Conversions { return 1; } - tbase= getNestedType(tbase, TDEF); if (tbase instanceof ICPPClassType) { int n= calculateInheritanceDepth(maxdepth - 1, tbase, ancestorToFind); if (n > 0) @@ -531,38 +618,31 @@ public class Conversions { * [4.2] array-to-ptr * [4.3] function-to-ptr */ - private static final boolean lvalue_to_rvalue(final Cost cost) throws DOMException { + private static final boolean lvalue_to_rvalue(final Cost cost, boolean isLValue) throws DOMException { // target should not be a reference here. boolean isConverted= false; IType target = getNestedType(cost.target, REF | TDEF); - IType source= getNestedType(cost.source, TDEF); + IType source= getNestedType(cost.source, REF | TDEF); // 4.1 lvalue to rvalue - IType srcRValue= getNestedType(source, REF | TDEF); - if (source instanceof ICPPReferenceType) { + if (isLValue) { // 4.1 lvalue of non-function and non-array - if (!(srcRValue instanceof IFunctionType) && !(srcRValue instanceof IArrayType)) { + if (!(source instanceof IFunctionType) && !(source 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, ALLCVQ | TDEF | REF); + IType unqualifiedSrcRValue= getNestedType(source, ALLCVQ | TDEF | REF); if (unqualifiedSrcRValue instanceof ICPPClassType) { - if (isCompleteType(unqualifiedSrcRValue)) { - source= srcRValue; - } else { - // ill-formed - cost.setRank(Rank.NO_MATCH); - return true; - } + cost.setRank(Rank.NO_MATCH); + return true; } else { source= unqualifiedSrcRValue; } - cost.setRank(Rank.LVALUE_TRANSFORMATION); isConverted= true; } } // 4.2 array to pointer conversion - if (!isConverted && srcRValue instanceof IArrayType) { - final IArrayType arrayType= (IArrayType) srcRValue; + if (!isConverted && source instanceof IArrayType) { + final IArrayType arrayType= (IArrayType) source; if (target instanceof IPointerType) { final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF); @@ -579,7 +659,6 @@ public class Conversions { if (lit.getKind() == IASTLiteralExpression.lk_string_literal) { source= new CPPPointerType(tmp, false, false); cost.setQualificationAdjustment(getCVQualifier(targetPtrTgt).isVolatile() ? 2 : 1); - cost.setRank(Rank.LVALUE_TRANSFORMATION); isConverted= true; } } @@ -589,7 +668,6 @@ public class Conversions { } if (!isConverted && (target instanceof IPointerType || target instanceof IBasicType)) { source = new CPPPointerType(getNestedType(arrayType.getType(), TDEF)); - cost.setRank(Rank.LVALUE_TRANSFORMATION); isConverted= true; } } @@ -597,9 +675,8 @@ public class Conversions { // 4.3 function to pointer conversion if (!isConverted && target instanceof IPointerType) { final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF); - if (targetPtrTgt instanceof IFunctionType && srcRValue instanceof IFunctionType) { + if (targetPtrTgt instanceof IFunctionType && source instanceof IFunctionType) { source = new CPPPointerType(source); - cost.setRank(Rank.LVALUE_TRANSFORMATION); isConverted= true; } } @@ -849,30 +926,4 @@ public class Conversions { } return false; } - - /** - * @param type - * @return whether the specified type has an associated definition - */ - private static final boolean isCompleteType(IType type) { - type= getUltimateType(type, false); - if (type instanceof ICPPTemplateInstance) - return true; - if (type instanceof ICPPClassType) { - if (type instanceof IIndexFragmentBinding) { - try { - return ((IIndexFragmentBinding) type).hasDefinition(); - } catch (CoreException e) { - CCorePlugin.log(e); - } - } - try { - return ((ICPPClassType) type).getCompositeScope() != null; - } catch (DOMException e) { - return false; - } - } - - return true; - } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java index e87bcaf6eb9..52b7ad002cb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Cost.java @@ -24,9 +24,12 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; */ final class Cost { enum Rank { - IDENTITY, LVALUE_TRANSFORMATION, PROMOTION, CONVERSION, CONVERSION_PTR_BOOL, + IDENTITY, PROMOTION, CONVERSION, CONVERSION_PTR_BOOL, USER_DEFINED_CONVERSION, ELLIPSIS_CONVERSION, NO_MATCH } + enum ReferenceBinding { + RVALUE_REF_BINDS_RVALUE, LVALUE_REF, OTHER + } IType source; IType target; @@ -38,11 +41,13 @@ final class Cost { private int fQualificationAdjustments; private int fInheritanceDistance; private ICPPFunction fUserDefinedConversion; + private ReferenceBinding fReferenceBinding; public Cost(IType s, IType t, Rank rank) { source = s; target = t; fRank= rank; + fReferenceBinding= ReferenceBinding.OTHER; } public Rank getRank() { @@ -53,6 +58,11 @@ final class Cost { fRank= rank; } + public void setReferenceBinding(ReferenceBinding binding) { + fReferenceBinding= binding; + } + + public boolean isAmbiguousUDC() { return fAmbiguousUDC; } @@ -79,9 +89,6 @@ final class Cost { public void setQualificationAdjustment(int adjustment) { fQualificationAdjustments= adjustment; - if (adjustment != 0 && fRank == Rank.IDENTITY) { - fRank= Rank.LVALUE_TRANSFORMATION; - } } /** @@ -130,13 +137,21 @@ final class Cost { if (cmp != 0) return cmp; + if (fReferenceBinding == ReferenceBinding.LVALUE_REF) { + if (other.fReferenceBinding == ReferenceBinding.RVALUE_REF_BINDS_RVALUE) + return 1; + } else if (fReferenceBinding == ReferenceBinding.RVALUE_REF_BINDS_RVALUE) { + if (other.fReferenceBinding == ReferenceBinding.LVALUE_REF) + return -1; + } + int qdiff= fQualificationAdjustments ^ other.fQualificationAdjustments; if (qdiff != 0) { if ((fQualificationAdjustments & qdiff) == 0) return -1; if ((other.fQualificationAdjustments & qdiff) == 0) return 1; - } + } return 0; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java index f789cd476ed..0121ab087a6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java @@ -33,6 +33,12 @@ class FunctionCost { fSourceIsLValue= new BitSet(paramCount); } + public FunctionCost(IFunction fn, Cost cost) { + fFunction= fn; + fCosts= new Cost[] {cost}; + fSourceIsLValue= null; // no udc will be performed + } + public int getLength() { return fCosts.length; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index fb802d5b36c..f5a54084b94 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -14,6 +14,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; +import java.util.BitSet; import java.util.Collections; import java.util.List; import java.util.Map; @@ -66,6 +67,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; @@ -108,6 +110,7 @@ public class LookupData { private Object[] functionArgs; private IType[] functionArgTypes; public ProblemBinding problem; + private BitSet functionArgLValues; public LookupData(IASTName n) { astName = n; @@ -600,7 +603,7 @@ public class LookupData { functionArgTypes= new IType[pdecls.length]; for (int i = 0; i < pdecls.length; i++) { IASTParameterDeclaration p = pdecls[i]; - functionArgTypes[i]= CPPVisitor.createType(p.getDeclarator()); + functionArgTypes[i]= SemanticUtil.getSimplifiedType(CPPVisitor.createType(p.getDeclarator())); } } else if (functionArgs instanceof IASTExpression[]) { IASTExpression[] exprs= (IASTExpression[]) functionArgs; @@ -608,13 +611,37 @@ public class LookupData { for (int i = 0; i < exprs.length; i++) { IASTExpression e = exprs[i]; IType etype= e.getExpressionType(); - functionArgTypes[i]= etype; + functionArgTypes[i]= SemanticUtil.getSimplifiedType(etype); } - } } return functionArgTypes; } + + public BitSet getFunctionArgumentLValues() { + if (functionArgLValues == null) { + functionArgLValues= new BitSet(); + IASTExpression[] args= getFunctionArguments(); + if (args != null) { + for (int i = 0; i < args.length; i++) { + final IASTExpression arg = args[i]; + if (arg != null) { + functionArgLValues.set(i, arg.isLValue()); + } + } + } else { + IType[] argTypes= getFunctionArgumentTypes(); + if (argTypes != null) { + for (int i = 0; i < argTypes.length; i++) { + IType t= argTypes[i]; + functionArgLValues.set(i, t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference()); + } + } + } + } + return functionArgLValues; + } + public void setFunctionArgumentTypes(IType[] paramTypes) { functionArgTypes= paramTypes; 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 23b08505d01..7fbb368181e 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 @@ -275,8 +275,18 @@ public class SemanticUtil { return type; return replaceNestedType((ITypeContainer) atype, newNested); } - } else if ((options & REF) != 0 && type instanceof ICPPReferenceType) { - t= ((ICPPReferenceType) type).getType(); + } else if (type instanceof ICPPReferenceType) { + final ICPPReferenceType rt = (ICPPReferenceType) type; + if ((options & REF) != 0) { + t= rt.getType(); + } else if (tdef) { + // a typedef within the reference type can influence whether the reference is lvalue or rvalue + IType nested= rt.getType(); + IType newNested = getNestedType(nested, TDEF); + if (nested == newNested) + return type; + return replaceNestedType((ITypeContainer) rt, newNested); + } } if (t == null) return type; @@ -323,6 +333,28 @@ public class SemanticUtil { } return type; } + + static boolean isSimplified(IType type) { + if (type instanceof ICPPFunctionType) { + final ICPPFunctionType ft = (ICPPFunctionType) type; + if (!isSimplified(ft.getReturnType())) + return false; + + IType[] ps = ft.getParameterTypes(); + for (IType p : ps) { + if (!isSimplified(p)) + return false; + } + return true; + } + if (type instanceof ITypedef) { + return false; + } + if (type instanceof ITypeContainer) { + return isSimplified(((ITypeContainer) type).getType()); + } + return true; + } public static IType replaceNestedType(ITypeContainer type, IType newNestedType) { if (newNestedType == null) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java index f7cf8f1b927..55a42dee834 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java @@ -161,7 +161,7 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { IType r= rt.getType(); IType r2= getCompositeType(r); if (r != r2) { - return new CPPReferenceType(r2); + return new CPPReferenceType(r2, rt.isRValueReference()); } return rt; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NodeContainer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NodeContainer.java index 7e6362201fe..01aa60e9d99 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NodeContainer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NodeContainer.java @@ -172,7 +172,7 @@ public class NodeContainer { declarator.addPointerOperator(new CASTPointer()); break; case CPP: - declarator.addPointerOperator(new CPPASTReferenceOperator()); + declarator.addPointerOperator(new CPPASTReferenceOperator(false)); break; } } diff --git a/upc/org.eclipse.cdt.core.parser.upc/src/org/eclipse/cdt/internal/core/dom/parser/upc/ast/UPCASTKeywordExpression.java b/upc/org.eclipse.cdt.core.parser.upc/src/org/eclipse/cdt/internal/core/dom/parser/upc/ast/UPCASTKeywordExpression.java index 1e3b45d7ee1..1e9a566f46a 100644 --- a/upc/org.eclipse.cdt.core.parser.upc/src/org/eclipse/cdt/internal/core/dom/parser/upc/ast/UPCASTKeywordExpression.java +++ b/upc/org.eclipse.cdt.core.parser.upc/src/org/eclipse/cdt/internal/core/dom/parser/upc/ast/UPCASTKeywordExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2008 IBM Corporation and others. + * Copyright (c) 2006, 2009 IBM Corporation 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 @@ -11,7 +11,6 @@ package org.eclipse.cdt.internal.core.dom.parser.upc.ast; import org.eclipse.cdt.core.dom.ast.ASTVisitor; -import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.upc.ast.IUPCASTKeywordExpression; @@ -50,7 +49,10 @@ public class UPCASTKeywordExpression extends ASTNode implements IUPCASTKeywordEx return new CBasicType(Kind.eInt, 0, this); } - + public boolean isLValue() { + return false; + } + @Override public boolean accept(ASTVisitor visitor) { if(visitor.shouldVisitExpressions) { |