mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 17:56:01 +02:00
RValue References: Implementation and testcases, bug 294730.
This commit is contained in:
parent
042f47dbef
commit
99148105b3
60 changed files with 1066 additions and 375 deletions
|
@ -51,7 +51,8 @@ public class ASTComparer extends Assert {
|
||||||
"isReference",
|
"isReference",
|
||||||
"isAssociatedWithLastName",
|
"isAssociatedWithLastName",
|
||||||
"getNestingLevel",
|
"getNestingLevel",
|
||||||
"getImplicitNames"
|
"getImplicitNames",
|
||||||
|
"isLValue"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Iterator;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTSignatureUtil;
|
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.EScopeKind;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
|
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||||
|
@ -7750,5 +7751,157 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
final String code= getAboveComment();
|
final String code= getAboveComment();
|
||||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4296,8 +4296,51 @@ public class AST2TemplateTests extends AST2BaseTest {
|
||||||
// int a=1;
|
// int a=1;
|
||||||
// a OPASSIGN(>>) 1;
|
// a OPASSIGN(>>) 1;
|
||||||
// }
|
// }
|
||||||
public void testTokenPasteShiftROperaotr_261268() throws Exception {
|
public void testTokenPasteShiftROperator_261268() throws Exception {
|
||||||
final String code= getAboveComment();
|
final String code= getAboveComment();
|
||||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
* Doug Schaefer (QNX) - Initial API and implementation
|
* Doug Schaefer (QNX) - Initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
package org.eclipse.cdt.core.dom;
|
package org.eclipse.cdt.core.dom;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.model.ICProject;
|
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_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$
|
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$
|
public static final String ID_FULL_INDEXER= "org.eclipse.cdt.core.domsourceindexer"; //$NON-NLS-1$
|
||||||
|
|
||||||
// Getting and setting indexer Ids
|
// Getting and setting indexer Ids
|
||||||
|
|
|
@ -350,7 +350,11 @@ public class ASTTypeUtil {
|
||||||
result.append(getArgumentListString(inst.getTemplateArguments(), normalize));
|
result.append(getArgumentListString(inst.getTemplateArguments(), normalize));
|
||||||
}
|
}
|
||||||
} else if (type instanceof ICPPReferenceType) {
|
} 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) {
|
} else if (type instanceof IEnumeration) {
|
||||||
result.append(Keywords.ENUM);
|
result.append(Keywords.ENUM);
|
||||||
result.append(SPACE);
|
result.append(SPACE);
|
||||||
|
@ -451,6 +455,7 @@ public class ASTTypeUtil {
|
||||||
// push all of the types onto the stack
|
// push all of the types onto the stack
|
||||||
int i = 0;
|
int i = 0;
|
||||||
IQualifierType cvq= null;
|
IQualifierType cvq= null;
|
||||||
|
ICPPReferenceType ref= null;
|
||||||
while (type != null && ++i < 100) {
|
while (type != null && ++i < 100) {
|
||||||
if (!normalize) {
|
if (!normalize) {
|
||||||
types = (IType[]) ArrayUtil.append(IType.class, types, type);
|
types = (IType[]) ArrayUtil.append(IType.class, types, type);
|
||||||
|
@ -461,19 +466,38 @@ public class ASTTypeUtil {
|
||||||
if (type instanceof ITypedef) {
|
if (type instanceof ITypedef) {
|
||||||
// skip it
|
// skip it
|
||||||
} else {
|
} else {
|
||||||
if (cvq != null) {
|
if (type instanceof ICPPReferenceType) {
|
||||||
if (type instanceof IQualifierType || type instanceof IPointerType) {
|
// reference types ignore cv-qualifiers
|
||||||
type= SemanticUtil.addQualifiers(type, cvq.isConst(), cvq.isVolatile());
|
cvq=null;
|
||||||
cvq= null;
|
// lvalue references win over rvalue references
|
||||||
} else {
|
if (ref == null || ref.isRValueReference()) {
|
||||||
types = (IType[]) ArrayUtil.append(IType.class, types, cvq);
|
// delay reference to see if there are more
|
||||||
|
ref= (ICPPReferenceType) type;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (type instanceof IQualifierType) {
|
|
||||||
cvq= (IQualifierType) type;
|
|
||||||
} else {
|
} 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) {
|
if (type instanceof ITypeContainer) {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Doug Schaefer (IBM) - Initial API and implementation
|
* Doug Schaefer (IBM) - Initial API and implementation
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.dom.ast;
|
package org.eclipse.cdt.core.dom.ast;
|
||||||
|
|
||||||
|
@ -24,6 +25,13 @@ public interface IASTExpression extends IASTNode {
|
||||||
|
|
||||||
public IType getExpressionType();
|
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
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -91,15 +91,15 @@ public interface IASTLiteralExpression extends IASTExpression {
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public void setValue(char[] value);
|
public void setValue(char[] value);
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated, use {@link #setValue(char[])}, instead.
|
|
||||||
*/
|
|
||||||
public void setValue(String value);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public IASTLiteralExpression copy();
|
public IASTLiteralExpression copy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Replaced by {@link #setValue(char[])}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void setValue(String value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Doug Schaefer (IBM) - Initial API and implementation
|
* Doug Schaefer (IBM) - Initial API and implementation
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.dom.ast.cpp;
|
package org.eclipse.cdt.core.dom.ast.cpp;
|
||||||
|
|
||||||
|
@ -20,6 +21,12 @@ import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
|
||||||
*/
|
*/
|
||||||
public interface ICPPASTReferenceOperator extends 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
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -39,12 +39,6 @@ import org.eclipse.cdt.core.parser.IScanner;
|
||||||
*/
|
*/
|
||||||
public interface ICPPNodeFactory extends INodeFactory {
|
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
|
* Creates a new translation unit that cooperates with the given scanner in order
|
||||||
* to track macro-expansions and location information.
|
* to track macro-expansions and location information.
|
||||||
|
@ -152,8 +146,12 @@ public interface ICPPNodeFactory extends INodeFactory {
|
||||||
|
|
||||||
public IGPPASTPointer newPointerGPP();
|
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 ICPPASTPointerToMember newPointerToMember(IASTName name);
|
||||||
|
|
||||||
public IGPPASTPointerToMember newPointerToMemberGPP(IASTName name);
|
public IGPPASTPointerToMember newPointerToMemberGPP(IASTName name);
|
||||||
|
@ -183,4 +181,14 @@ public interface ICPPNodeFactory extends INodeFactory {
|
||||||
*/
|
*/
|
||||||
public ICPPASTStaticAssertDeclaration newStaticAssertion(IASTExpression condition, ICPPASTLiteralExpression message);
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Andrew Niefer (IBM Corporation) - initial API and implementation
|
* Andrew Niefer (IBM Corporation) - initial API and implementation
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.dom.ast.cpp;
|
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 {
|
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();
|
public IType getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this is an rvalue reference (e.g: int&&)
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
public boolean isRValueReference();
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,4 +133,8 @@ public abstract class ASTAmbiguousNode extends ASTNode {
|
||||||
afterResolution(resolver, bestAlternative);
|
afterResolution(resolver, bestAlternative);
|
||||||
return bestAlternative;
|
return bestAlternative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,4 +86,8 @@ public abstract class ASTTypeIdInitializerExpression extends ASTNode implements
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1152,6 +1152,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final IASTExpression castExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
protected final IASTExpression castExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||||
|
|
|
@ -120,4 +120,8 @@ public class CASTArraySubscriptExpression extends ASTNode implements
|
||||||
return ((IArrayType)t).getType();
|
return ((IArrayType)t).getType();
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,4 +161,22 @@ public class CASTBinaryExpression extends ASTNode implements
|
||||||
}
|
}
|
||||||
return t1;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,4 +121,8 @@ public class CASTCastExpression extends ASTNode implements IASTCastExpression, I
|
||||||
IASTTypeId id= getTypeId();
|
IASTTypeId id= getTypeId();
|
||||||
return CVisitor.createType(id.getAbstractDeclarator());
|
return CVisitor.createType(id.getAbstractDeclarator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,5 +85,15 @@ public class CASTCompoundStatementExpression extends ASTNode implements IGNUASTC
|
||||||
}
|
}
|
||||||
return null;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,4 +144,8 @@ public class CASTConditionalExpression extends ASTNode implements
|
||||||
return t3;
|
return t3;
|
||||||
return t2;
|
return t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,4 +102,13 @@ public class CASTExpressionList extends ASTNode implements IASTExpressionList,
|
||||||
}
|
}
|
||||||
return null;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,14 @@ public class CASTFieldReference extends ASTNode implements IASTFieldReference, I
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
if (isPointerDereference())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return getFieldOwner().isLValue();
|
||||||
|
}
|
||||||
|
|
||||||
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
|
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
|
||||||
return CVisitor.findBindingsForContentAssist(n, isPrefix);
|
return CVisitor.findBindingsForContentAssist(n, isPrefix);
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,4 +120,8 @@ public class CASTFunctionCallExpression extends ASTNode implements
|
||||||
return ((IFunctionType) type).getReturnType();
|
return ((IFunctionType) type).getReturnType();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,10 @@ public class CASTIdExpression extends ASTNode implements IASTIdExpression, IASTC
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
|
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
|
||||||
IBinding[] bindings = CVisitor.findBindingsForContentAssist(n, isPrefix);
|
IBinding[] bindings = CVisitor.findBindingsForContentAssist(n, isPrefix);
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,11 @@ public class CASTLiteralExpression extends ASTNode implements IASTLiteralExpress
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return getKind() == IASTLiteralExpression.lk_string_literal;
|
||||||
|
}
|
||||||
|
|
||||||
private IType classifyTypeOfFloatLiteral() {
|
private IType classifyTypeOfFloatLiteral() {
|
||||||
final char[] lit= getValue();
|
final char[] lit= getValue();
|
||||||
final int len= lit.length;
|
final int len= lit.length;
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -59,5 +59,8 @@ public class CASTProblemExpression extends CASTProblemOwner implements IASTProbl
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,4 +90,8 @@ public class CASTTypeIdExpression extends ASTNode implements IASTTypeIdExpressio
|
||||||
}
|
}
|
||||||
return CVisitor.createType(typeId.getAbstractDeclarator());
|
return CVisitor.createType(typeId.getAbstractDeclarator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,5 +121,17 @@ public class CASTUnaryExpression extends ASTNode implements IASTUnaryExpression,
|
||||||
}
|
}
|
||||||
return exprType; // return the original
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* John Camelon (IBM) - Initial API and implementation
|
* John Camelon (IBM) - Initial API and implementation
|
||||||
* Mike Kucera (IBM)
|
* Mike Kucera (IBM)
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
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.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
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.CPPSemantics;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author jcamelon
|
|
||||||
*/
|
|
||||||
public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTArraySubscriptExpression, IASTAmbiguityParent {
|
public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTArraySubscriptExpression, IASTAmbiguityParent {
|
||||||
|
|
||||||
private IASTExpression subscriptExp;
|
private IASTExpression subscriptExp;
|
||||||
private IASTExpression arrayExpression;
|
private IASTExpression arrayExpression;
|
||||||
|
private ICPPFunction overload= UNINITIALIZED_FUNCTION;
|
||||||
|
|
||||||
private IASTImplicitName[] implicitNames = null;
|
private IASTImplicitName[] implicitNames = null;
|
||||||
|
|
||||||
|
@ -104,7 +104,15 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTAr
|
||||||
|
|
||||||
|
|
||||||
public ICPPFunction getOverload() {
|
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
|
@Override
|
||||||
|
@ -156,28 +164,36 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTAr
|
||||||
}
|
}
|
||||||
|
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
|
ICPPFunction op = getOverload();
|
||||||
|
if (op != null) {
|
||||||
|
try {
|
||||||
|
return op.getType().getReturnType();
|
||||||
|
} catch (DOMException e) {
|
||||||
|
return e.getProblem();
|
||||||
|
}
|
||||||
|
}
|
||||||
IType t = getArrayExpression().getExpressionType();
|
IType t = getArrayExpression().getExpressionType();
|
||||||
t= SemanticUtil.getUltimateTypeUptoPointers(t);
|
t= SemanticUtil.getUltimateTypeUptoPointers(t);
|
||||||
try {
|
if (t instanceof ICPPUnknownType) {
|
||||||
if (t instanceof ICPPUnknownType) {
|
return CPPUnknownClass.createUnnamedInstance();
|
||||||
return CPPUnknownClass.createUnnamedInstance();
|
}
|
||||||
}
|
if (t instanceof IPointerType) {
|
||||||
if (t instanceof ICPPClassType) {
|
return ((IPointerType) t).getType();
|
||||||
ICPPFunction op = getOverload();
|
}
|
||||||
if (op != null) {
|
if (t instanceof IArrayType) {
|
||||||
return op.getType().getReturnType();
|
return ((IArrayType) t).getType();
|
||||||
}
|
|
||||||
}
|
|
||||||
if (t instanceof IPointerType) {
|
|
||||||
return ((IPointerType) t).getType();
|
|
||||||
}
|
|
||||||
if (t instanceof IArrayType) {
|
|
||||||
return ((IArrayType) t).getType();
|
|
||||||
}
|
|
||||||
} catch (DOMException e) {
|
|
||||||
return e.getProblem();
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
ICPPFunction op = getOverload();
|
||||||
|
if (op != null) {
|
||||||
|
try {
|
||||||
|
return CPPVisitor.isLValueReference(op.getType().getReturnType());
|
||||||
|
} catch (DOMException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,6 +172,31 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
||||||
return overload = CPPSemantics.findOverloadedOperator(this);
|
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() {
|
private IType createExpressionType() {
|
||||||
// Check for overloaded operator.
|
// Check for overloaded operator.
|
||||||
ICPPFunction o= getOverload();
|
ICPPFunction o= getOverload();
|
||||||
|
|
|
@ -28,6 +28,7 @@ public class CPPASTCastExpression extends ASTNode implements ICPPASTCastExpressi
|
||||||
private int op;
|
private int op;
|
||||||
private IASTExpression operand;
|
private IASTExpression operand;
|
||||||
private IASTTypeId typeId;
|
private IASTTypeId typeId;
|
||||||
|
private IType fType;
|
||||||
|
|
||||||
public CPPASTCastExpression() {
|
public CPPASTCastExpression() {
|
||||||
}
|
}
|
||||||
|
@ -117,6 +118,15 @@ public class CPPASTCastExpression extends ASTNode implements ICPPASTCastExpressi
|
||||||
}
|
}
|
||||||
|
|
||||||
public IType getExpressionType() {
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* 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;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
@ -85,4 +86,15 @@ public class CPPASTCompoundStatementExpression extends ASTNode implements IGNUAS
|
||||||
}
|
}
|
||||||
return null;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* 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;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
@ -144,4 +145,8 @@ public class CPPASTConditionalExpression extends ASTNode implements
|
||||||
return t3;
|
return t3;
|
||||||
return t2;
|
return t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* John Camelon (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;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
@ -151,4 +152,8 @@ public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpr
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
return CPPSemantics.VOID_TYPE;
|
return CPPSemantics.VOID_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* John Camelon (IBM) - Initial API and implementation
|
* John Camelon (IBM) - Initial API and implementation
|
||||||
* Mike Kucera (IBM) - implicit names
|
* Mike Kucera (IBM) - implicit names
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
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.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
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.CPPSemantics;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
|
|
||||||
|
|
||||||
public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionList, IASTAmbiguityParent {
|
public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionList, IASTAmbiguityParent {
|
||||||
|
@ -172,22 +174,44 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
ICPPFunction[] overloads = getOverloads();
|
ICPPFunction[] overloads = getOverloads();
|
||||||
if(overloads.length > 0) {
|
if (overloads.length > 0) {
|
||||||
ICPPFunction last = overloads[overloads.length-1];
|
ICPPFunction last = overloads[overloads.length - 1];
|
||||||
if(last != null) {
|
if (last != null) {
|
||||||
try {
|
try {
|
||||||
return last.getType().getReturnType();
|
return last.getType().getReturnType();
|
||||||
} catch (DOMException e) { }
|
} catch (DOMException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (int i = expressions.length-1; i >= 0 ; i--) {
|
|
||||||
IASTExpression expr= expressions[i];
|
for (int i = expressions.length - 1; i >= 0; i--) {
|
||||||
|
IASTExpression expr = expressions[i];
|
||||||
if (expr != null)
|
if (expr != null)
|
||||||
return expr.getExpressionType();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,12 @@
|
||||||
* John Camelon (IBM) - Initial API and implementation
|
* John Camelon (IBM) - Initial API and implementation
|
||||||
* Bryan Wilkinson (QNX)
|
* Bryan Wilkinson (QNX)
|
||||||
* Mike Kucera (IBM)
|
* Mike Kucera (IBM)
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
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.ArrayList;
|
||||||
import java.util.List;
|
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.IVariable;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
|
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.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.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.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
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.CPPSemantics;
|
||||||
|
@ -205,6 +210,26 @@ public class CPPASTFieldReference extends ASTNode implements
|
||||||
return null;
|
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) {
|
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
|
||||||
IBinding[] bindings = CPPSemantics.findBindingsForContentAssist(n, isPrefix);
|
IBinding[] bindings = CPPSemantics.findBindingsForContentAssist(n, isPrefix);
|
||||||
List<IBinding> filtered = new ArrayList<IBinding>();
|
List<IBinding> filtered = new ArrayList<IBinding>();
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* John Camelon (IBM) - Initial API and implementation
|
* John Camelon (IBM) - Initial API and implementation
|
||||||
* Mike Kucera (IBM) - implicit names
|
* Mike Kucera (IBM) - implicit names
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
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.IASTAmbiguityParent;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
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.CPPSemantics;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,7 +201,11 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IType computeExpressionType() {
|
public boolean isLValue() {
|
||||||
|
return CPPVisitor.isLValueReference(getExpressionType());
|
||||||
|
}
|
||||||
|
|
||||||
|
private IType computeExpressionType() {
|
||||||
overload= null;
|
overload= null;
|
||||||
try {
|
try {
|
||||||
IType t= null;
|
IType t= null;
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM - Initial API and implementation
|
* John Camelon (IBM) - Initial API and implementation
|
||||||
* Bryan Wilkinson (QNX)
|
* Bryan Wilkinson (QNX)
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
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.CPPSemantics;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author jcamelon
|
|
||||||
*/
|
|
||||||
public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, IASTCompletionContext {
|
public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, IASTCompletionContext {
|
||||||
|
|
||||||
private IASTName name;
|
private IASTName name;
|
||||||
|
@ -112,6 +110,14 @@ public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, IAS
|
||||||
return null;
|
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) {
|
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
|
||||||
return CPPSemantics.findBindingsForContentAssist(n, isPrefix);
|
return CPPSemantics.findBindingsForContentAssist(n, isPrefix);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
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.IBasicType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
|
@ -113,6 +114,10 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return getKind() == IASTLiteralExpression.lk_string_literal;
|
||||||
|
}
|
||||||
|
|
||||||
private IValue getStringLiteralSize() {
|
private IValue getStringLiteralSize() {
|
||||||
char[] value= getValue();
|
char[] value= getValue();
|
||||||
int length= value.length-1;
|
int length= value.length-1;
|
||||||
|
|
|
@ -256,4 +256,8 @@ public class CPPASTNewExpression extends ASTNode implements
|
||||||
}
|
}
|
||||||
return new CPPPointerType(t);
|
return new CPPPointerType(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM - Initial API and implementation
|
* John Camelon (IBM) - Initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
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.IASTProblemExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author jcamelon
|
|
||||||
*/
|
|
||||||
public class CPPASTProblemExpression extends CPPASTProblemOwner implements IASTProblemExpression {
|
public class CPPASTProblemExpression extends CPPASTProblemOwner implements IASTProblemExpression {
|
||||||
|
|
||||||
public CPPASTProblemExpression() {
|
public CPPASTProblemExpression() {
|
||||||
|
@ -58,4 +55,8 @@ public class CPPASTProblemExpression extends CPPASTProblemOwner implements IASTP
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,18 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
*/
|
*/
|
||||||
public class CPPASTReferenceOperator extends ASTNode implements ICPPASTReferenceOperator {
|
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() {
|
public CPPASTReferenceOperator copy() {
|
||||||
CPPASTReferenceOperator copy = new CPPASTReferenceOperator();
|
CPPASTReferenceOperator copy = new CPPASTReferenceOperator(fIsRValue);
|
||||||
copy.setOffsetAndLength(this);
|
copy.setOffsetAndLength(this);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author jcamelon
|
|
||||||
*/
|
|
||||||
public class CPPASTSimpleTypeConstructorExpression extends ASTNode implements
|
public class CPPASTSimpleTypeConstructorExpression extends ASTNode implements
|
||||||
ICPPASTSimpleTypeConstructorExpression, IASTAmbiguityParent {
|
ICPPASTSimpleTypeConstructorExpression, IASTAmbiguityParent {
|
||||||
|
|
||||||
|
@ -100,4 +97,8 @@ public class CPPASTSimpleTypeConstructorExpression extends ASTNode implements
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
return new CPPBasicType(CPPBasicType.getKind(st), 0);
|
return new CPPBasicType(CPPBasicType.getKind(st), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,21 +6,18 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* 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;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
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.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeIdExpression;
|
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.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author jcamelon
|
|
||||||
*/
|
|
||||||
public class CPPASTTypeIdExpression extends ASTNode implements ICPPASTTypeIdExpression {
|
public class CPPASTTypeIdExpression extends ASTNode implements ICPPASTTypeIdExpression {
|
||||||
|
|
||||||
private int op;
|
private int op;
|
||||||
|
@ -86,11 +83,21 @@ public class CPPASTTypeIdExpression extends ASTNode implements ICPPASTTypeIdExpr
|
||||||
|
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
switch (getOperator()) {
|
switch (getOperator()) {
|
||||||
case IASTTypeIdExpression.op_sizeof:
|
case op_sizeof:
|
||||||
return CPPVisitor.get_SIZE_T(this);
|
return CPPVisitor.get_SIZE_T(this);
|
||||||
case IASTTypeIdExpression.op_typeid:
|
case op_typeid:
|
||||||
return CPPVisitor.get_type_info(this);
|
return CPPVisitor.get_type_info(this);
|
||||||
}
|
}
|
||||||
return CPPVisitor.createType(getTypeId());
|
return CPPVisitor.createType(getTypeId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
switch(getOperator()) {
|
||||||
|
case op_typeid:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* 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;
|
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.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author jcamelon
|
|
||||||
*/
|
|
||||||
public class CPPASTTypenameExpression extends ASTNode implements
|
public class CPPASTTypenameExpression extends ASTNode implements
|
||||||
ICPPASTTypenameExpression, IASTAmbiguityParent {
|
ICPPASTTypenameExpression, IASTAmbiguityParent {
|
||||||
|
|
||||||
|
@ -135,4 +133,8 @@ public class CPPASTTypenameExpression extends ASTNode implements
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,6 +271,26 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
|
||||||
return origType;
|
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() {
|
private IType findOperatorReturnType() {
|
||||||
ICPPFunction operatorFunction = getOverload();
|
ICPPFunction operatorFunction = getOverload();
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
||||||
char[] className = name.getLookupKey();
|
char[] className = name.getLookupKey();
|
||||||
|
|
||||||
IParameter[] voidPs = new IParameter[] { new CPPParameter(CPPSemantics.VOID_TYPE, 0) };
|
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) };
|
IParameter[] ps = new IParameter[] { new CPPParameter(pType, 0) };
|
||||||
|
|
||||||
int i= 0;
|
int i= 0;
|
||||||
|
@ -124,7 +124,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
||||||
|
|
||||||
if (!ia.hasUserDeclaredCopyAssignmentOperator()) {
|
if (!ia.hasUserDeclaredCopyAssignmentOperator()) {
|
||||||
//copy assignment operator: A& operator = (const A &)
|
//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);
|
ICPPFunctionType ft= CPPVisitor.createImplicitFunctionType(refType, ps, false, false);
|
||||||
ICPPMethod m = new CPPImplicitMethod(this, OverloadableOperator.ASSIGN.toCharArray(), ft, ps);
|
ICPPMethod m = new CPPImplicitMethod(this, OverloadableOperator.ASSIGN.toCharArray(), ft, ps);
|
||||||
implicits[i++] = m;
|
implicits[i++] = m;
|
||||||
|
|
|
@ -454,7 +454,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICPPASTReferenceOperator newReferenceOperator() {
|
public ICPPASTReferenceOperator newReferenceOperator() {
|
||||||
return new CPPASTReferenceOperator();
|
return new CPPASTReferenceOperator(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICPPASTReferenceOperator newReferenceOperator(boolean isRValueReference) {
|
||||||
|
return new CPPASTReferenceOperator(isRValueReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICPPASTPointerToMember newPointerToMember(IASTName name) {
|
public ICPPASTPointerToMember newPointerToMember(IASTName name) {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Andrew Niefer (IBM Corporation) - initial API and implementation
|
* Andrew Niefer (IBM Corporation) - initial API and implementation
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
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;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
public class CPPReferenceType implements ICPPReferenceType, ITypeContainer, ISerializableType {
|
public class CPPReferenceType implements ICPPReferenceType, ITypeContainer, ISerializableType {
|
||||||
IType type = null;
|
private IType fType = null;
|
||||||
|
private boolean fIsRValue;
|
||||||
|
|
||||||
public CPPReferenceType(IType type) {
|
public CPPReferenceType(IType type, boolean isRValue) {
|
||||||
this.type = type;
|
fIsRValue= isRValue;
|
||||||
|
setType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IType getType() {
|
public IType getType() {
|
||||||
return type;
|
return fType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRValueReference() {
|
||||||
|
return fIsRValue;
|
||||||
|
}
|
||||||
|
|
||||||
public void setType(IType t) {
|
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) {
|
public boolean isSameType(IType obj) {
|
||||||
|
@ -40,11 +52,36 @@ public class CPPReferenceType implements ICPPReferenceType, ITypeContainer, ISer
|
||||||
if (obj instanceof ITypedef)
|
if (obj instanceof ITypedef)
|
||||||
return ((ITypedef)obj).isSameType(this);
|
return ((ITypedef)obj).isSameType(this);
|
||||||
|
|
||||||
if (type == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (obj instanceof ICPPReferenceType) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -67,12 +104,15 @@ public class CPPReferenceType implements ICPPReferenceType, ITypeContainer, ISer
|
||||||
|
|
||||||
public void marshal(ITypeMarshalBuffer buffer) throws CoreException {
|
public void marshal(ITypeMarshalBuffer buffer) throws CoreException {
|
||||||
int firstByte= ITypeMarshalBuffer.REFERENCE;
|
int firstByte= ITypeMarshalBuffer.REFERENCE;
|
||||||
|
if (isRValueReference()) {
|
||||||
|
firstByte |= ITypeMarshalBuffer.FLAG1;
|
||||||
|
}
|
||||||
buffer.putByte((byte) firstByte);
|
buffer.putByte((byte) firstByte);
|
||||||
buffer.marshalType(getType());
|
buffer.marshalType(getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||||
IType nested= buffer.unmarshalType();
|
IType nested= buffer.unmarshalType();
|
||||||
return new CPPReferenceType(nested);
|
return new CPPReferenceType(nested, (firstByte & ITypeMarshalBuffer.FLAG1) != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2947,17 +2947,16 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
// __attribute__ in-between pointers
|
// __attribute__ in-between pointers
|
||||||
__attribute_decl_seq(supportAttributeSpecifiers, false);
|
__attribute_decl_seq(supportAttributeSpecifiers, false);
|
||||||
|
|
||||||
if (LT(1) == IToken.tAMPER) {
|
final int lt1 = LT(1);
|
||||||
// boolean isRestrict= false;
|
if (lt1 == IToken.tAMPER || lt1 == IToken.tAND) {
|
||||||
IToken lastToken= consume();
|
IToken endToken= consume();
|
||||||
final int from= lastToken.getOffset();
|
final int offset= endToken.getOffset();
|
||||||
|
|
||||||
if (allowCPPRestrict && LT(1) == IToken.t_restrict) {
|
if (allowCPPRestrict && LT(1) == IToken.t_restrict) {
|
||||||
// isRestrict= true;
|
endToken= consume();
|
||||||
lastToken= consume();
|
|
||||||
}
|
}
|
||||||
ICPPASTReferenceOperator refOp = nodeFactory.newReferenceOperator();
|
ICPPASTReferenceOperator refOp = nodeFactory.newReferenceOperator(lt1 == IToken.tAND);
|
||||||
((ASTNode) refOp).setOffsetAndLength(from, lastToken.getEndOffset()-from);
|
collection.add(setRange(refOp, offset, endToken.getEndOffset()));
|
||||||
collection.add(refOp);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -1799,7 +1800,7 @@ public class CPPSemantics {
|
||||||
return !b1FromIndex ? 1 : -1;
|
return !b1FromIndex ? 1 : -1;
|
||||||
} else if (b1FromIndex) {
|
} else if (b1FromIndex) {
|
||||||
// Both are from index.
|
// Both are from index.
|
||||||
if (data.tu != null) {
|
if (data != null && data.tu != null) {
|
||||||
boolean b1Reachable= isReachableFromAst(data.tu, b1);
|
boolean b1Reachable= isReachableFromAst(data.tu, b1);
|
||||||
boolean b2Reachable= isReachableFromAst(data.tu, b2);
|
boolean b2Reachable= isReachableFromAst(data.tu, b2);
|
||||||
if (b1Reachable != b2Reachable) {
|
if (b1Reachable != b2Reachable) {
|
||||||
|
@ -2047,7 +2048,7 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
|
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
|
// 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;
|
return firstViable;
|
||||||
|
|
||||||
// The arguments the function is being called with
|
// The arguments the function is being called with
|
||||||
final IASTExpression[] args= data.getFunctionArguments();
|
|
||||||
IType[] argTypes = data.getFunctionArgumentTypes();
|
IType[] argTypes = data.getFunctionArgumentTypes();
|
||||||
if (CPPTemplates.containsDependentType(argTypes)) {
|
if (CPPTemplates.containsDependentType(argTypes)) {
|
||||||
if (viableCount == 1)
|
if (viableCount == 1)
|
||||||
|
@ -2086,7 +2086,7 @@ public class CPPSemantics {
|
||||||
if (fn == null)
|
if (fn == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
final FunctionCost fnCost= costForFunctionCall(fn, argTypes, args, allowUDC, data);
|
final FunctionCost fnCost= costForFunctionCall(fn, allowUDC, data);
|
||||||
if (fnCost == null)
|
if (fnCost == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -2137,8 +2137,10 @@ public class CPPSemantics {
|
||||||
return bestFnCost.getFunction();
|
return bestFnCost.getFunction();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FunctionCost costForFunctionCall(IFunction fn, IType[] argTypes, IASTExpression[] args,
|
private static FunctionCost costForFunctionCall(IFunction fn, boolean allowUDC, LookupData data)
|
||||||
boolean allowUDC, LookupData data) throws DOMException {
|
throws DOMException {
|
||||||
|
IType[] argTypes = data.getFunctionArgumentTypes();
|
||||||
|
BitSet isLValue= data.getFunctionArgumentLValues();
|
||||||
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
|
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
|
||||||
if (ftype == null)
|
if (ftype == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -2149,9 +2151,7 @@ public class CPPSemantics {
|
||||||
implicitType = getImplicitType((ICPPMethod) fn, ftype.isConst(), ftype.isVolatile());
|
implicitType = getImplicitType((ICPPMethod) fn, ftype.isConst(), ftype.isVolatile());
|
||||||
if (data.firstArgIsImpliedMethodArg) {
|
if (data.firstArgIsImpliedMethodArg) {
|
||||||
argTypes = ArrayUtil.removeFirst(argTypes);
|
argTypes = ArrayUtil.removeFirst(argTypes);
|
||||||
if (args != null) {
|
isLValue = isLValue.get(1, isLValue.size());
|
||||||
args = ArrayUtil.removeFirst(args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2175,7 +2175,7 @@ public class CPPSemantics {
|
||||||
} else if (thisType.isSameType(implicitType)) {
|
} else if (thisType.isSameType(implicitType)) {
|
||||||
cost = new Cost(thisType, implicitType, Rank.IDENTITY);
|
cost = new Cost(thisType, implicitType, Rank.IDENTITY);
|
||||||
} else {
|
} 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 (cost.getRank() == Rank.NO_MATCH) {
|
||||||
if (CPPTemplates.isDependentType(implicitType) || CPPTemplates.isDependentType(thisType)) {
|
if (CPPTemplates.isDependentType(implicitType) || CPPTemplates.isDependentType(thisType)) {
|
||||||
IType s= getNestedType(thisType, TDEF|REF|CVTYPE);
|
IType s= getNestedType(thisType, TDEF|REF|CVTYPE);
|
||||||
|
@ -2195,12 +2195,11 @@ public class CPPSemantics {
|
||||||
|
|
||||||
final UDCMode udc = allowUDC ? UDCMode.deferUDC : UDCMode.noUDC;
|
final UDCMode udc = allowUDC ? UDCMode.deferUDC : UDCMode.noUDC;
|
||||||
for (int j = 0; j < sourceLen; j++) {
|
for (int j = 0; j < sourceLen; j++) {
|
||||||
final IType argType= argTypes[j];
|
final IType argType= SemanticUtil.getNestedType(argTypes[j], TDEF | REF);
|
||||||
if (argType == null)
|
if (argType == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
final IASTExpression arg= args != null && j < args.length ? args[j] : null;
|
final boolean sourceIsLValue = isLValue.get(j);
|
||||||
final boolean sourceIsLValue = arg != null && !CPPVisitor.isRValue(arg);
|
|
||||||
|
|
||||||
IType paramType;
|
IType paramType;
|
||||||
if (j < paramTypes.length) {
|
if (j < paramTypes.length) {
|
||||||
|
@ -2218,7 +2217,7 @@ public class CPPSemantics {
|
||||||
} else {
|
} else {
|
||||||
if (CPPTemplates.isDependentType(paramType))
|
if (CPPTemplates.isDependentType(paramType))
|
||||||
return CONTAINS_DEPENDENT_TYPES;
|
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)
|
if (cost.getRank() == Rank.NO_MATCH)
|
||||||
return null;
|
return null;
|
||||||
|
@ -2236,7 +2235,7 @@ public class CPPSemantics {
|
||||||
owner= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) owner);
|
owner= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) owner);
|
||||||
}
|
}
|
||||||
implicitType= SemanticUtil.addQualifiers(owner, isConst, isVolatile);
|
implicitType= SemanticUtil.addQualifiers(owner, isConst, isVolatile);
|
||||||
implicitType= new CPPReferenceType(implicitType);
|
implicitType= new CPPReferenceType(implicitType, false);
|
||||||
return implicitType;
|
return implicitType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,10 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
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.*;
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
|
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
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.CPPMethodTemplateSpecialization;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType;
|
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.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.CPPTemplateArgument;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateDefinition;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateDefinition;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeParameter;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeParameter;
|
||||||
|
@ -634,7 +634,7 @@ public class CPPTemplates {
|
||||||
* 14.8.2.1
|
* 14.8.2.1
|
||||||
*/
|
*/
|
||||||
static private ICPPTemplateArgument[] deduceTemplateFunctionArguments(ICPPFunctionTemplate template,
|
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 ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
|
||||||
final int length = tmplParams.length;
|
final int length = tmplParams.length;
|
||||||
if (tmplArgs.length > length)
|
if (tmplArgs.length > length)
|
||||||
|
@ -654,7 +654,7 @@ public class CPPTemplates {
|
||||||
result[i]= tmplArg;
|
result[i]= tmplArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!deduceTemplateParameterMapFromFunctionParameters(template, fnArgs, map, false))
|
if (!deduceTemplateParameterMapFromFunctionParameters(template, fnArgs, argIsLValue, map, false))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
|
@ -1360,7 +1360,7 @@ public class CPPTemplates {
|
||||||
return result;
|
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;
|
boolean requireTemplate= false;
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
|
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
|
||||||
|
@ -1399,7 +1399,7 @@ public class CPPTemplates {
|
||||||
}
|
}
|
||||||
CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length);
|
CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length);
|
||||||
try {
|
try {
|
||||||
ICPPTemplateArgument[] args= deduceTemplateFunctionArguments(template, templateArguments, fnArgs, map);
|
ICPPTemplateArgument[] args= deduceTemplateFunctionArguments(template, templateArguments, fnArgs, argIsLValue, map);
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
IBinding instance= instantiateFunctionTemplate(template, args);
|
IBinding instance= instantiateFunctionTemplate(template, args);
|
||||||
if (instance instanceof IFunction) {
|
if (instance instanceof IFunction) {
|
||||||
|
@ -1458,7 +1458,7 @@ public class CPPTemplates {
|
||||||
* returns <code>false</code> if there is no mapping.
|
* returns <code>false</code> if there is no mapping.
|
||||||
*/
|
*/
|
||||||
private static boolean deduceTemplateParameterMapFromFunctionParameters(ICPPFunctionTemplate template,
|
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 {
|
try {
|
||||||
IType[] fnPars = template.getType().getParameterTypes();
|
IType[] fnPars = template.getType().getParameterTypes();
|
||||||
if (fnPars.length == 0)
|
if (fnPars.length == 0)
|
||||||
|
@ -1478,12 +1478,24 @@ public class CPPTemplates {
|
||||||
IType par= instPars[j];
|
IType par= instPars[j];
|
||||||
boolean isDependentPar= isDependentType(par);
|
boolean isDependentPar= isDependentType(par);
|
||||||
if (checkExactMatch || isDependentPar) {
|
if (checkExactMatch || isDependentPar) {
|
||||||
|
boolean isReferenceTypeParameter= false;
|
||||||
|
IType arg = fnArgs[j];
|
||||||
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF); // adjustParameterType preserves typedefs
|
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF); // adjustParameterType preserves typedefs
|
||||||
// 14.8.2.1-2
|
// 14.8.2.1-2
|
||||||
final boolean isReferenceTypeParameter = par instanceof ICPPReferenceType;
|
if (par instanceof ICPPReferenceType) {
|
||||||
IType arg= getArgumentTypeForDeduction(fnArgs[j], isReferenceTypeParameter);
|
// If P is an rvalue reference to a cv-unqualified template parameter and the argument is an
|
||||||
if (isReferenceTypeParameter)
|
// 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);
|
par= SemanticUtil.getNestedType(par, SemanticUtil.REF | SemanticUtil.TDEF);
|
||||||
|
} else {
|
||||||
|
arg= getArgumentTypeForDeduction(arg, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (!checkExactMatch) {
|
if (!checkExactMatch) {
|
||||||
// 14.8.2.1-3
|
// 14.8.2.1-3
|
||||||
|
@ -1841,7 +1853,7 @@ public class CPPTemplates {
|
||||||
|
|
||||||
CPPTemplateParameterMap map= new CPPTemplateParameterMap(2);
|
CPPTemplateParameterMap map= new CPPTemplateParameterMap(2);
|
||||||
final IType[] transferredParameterTypes = ((ICPPFunction) transferredTemplate).getType().getParameterTypes();
|
final IType[] transferredParameterTypes = ((ICPPFunction) transferredTemplate).getType().getParameterTypes();
|
||||||
if (!deduceTemplateParameterMapFromFunctionParameters(f2, transferredParameterTypes, map, true))
|
if (!deduceTemplateParameterMapFromFunctionParameters(f2, transferredParameterTypes, new BitSet(), map, true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
final ICPPTemplateParameter[] tmplParams = f2.getTemplateParameters();
|
final ICPPTemplateParameter[] tmplParams = f2.getTemplateParameters();
|
||||||
|
@ -2078,7 +2090,7 @@ public class CPPTemplates {
|
||||||
} else if (paramType instanceof IArrayType) {
|
} else if (paramType instanceof IArrayType) {
|
||||||
paramType = new CPPPointerType(((IArrayType) paramType).getType());
|
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;
|
return cost != null && cost.getRank() != Rank.NO_MATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
|
||||||
@Override
|
@Override
|
||||||
protected int rwAssignmentToType(IType type, int indirection) {
|
protected int rwAssignmentToType(IType type, int indirection) {
|
||||||
if (indirection == 0) {
|
if (indirection == 0) {
|
||||||
if (!(type instanceof ICPPReferenceType)) {
|
if (!(type instanceof ICPPReferenceType) || ((ICPPReferenceType) type).isRValueReference()) {
|
||||||
return READ;
|
return READ;
|
||||||
}
|
}
|
||||||
type= ((ICPPReferenceType) type).getType();
|
type= ((ICPPReferenceType) type).getType();
|
||||||
|
|
|
@ -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.IASTInitializerExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerList;
|
import org.eclipse.cdt.core.dom.ast.IASTInitializerList;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
|
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.IASTName;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
@ -1617,7 +1616,8 @@ public class CPPVisitor extends ASTQueries {
|
||||||
} else if (ptrOp instanceof IASTPointer) {
|
} else if (ptrOp instanceof IASTPointer) {
|
||||||
type = new CPPPointerType(type, (IASTPointer) ptrOp);
|
type = new CPPPointerType(type, (IASTPointer) ptrOp);
|
||||||
} else if (ptrOp instanceof ICPPASTReferenceOperator) {
|
} else if (ptrOp instanceof ICPPASTReferenceOperator) {
|
||||||
type = new CPPReferenceType(type);
|
final ICPPASTReferenceOperator refOp = (ICPPASTReferenceOperator) ptrOp;
|
||||||
|
type = new CPPReferenceType(type, refOp.isRValueReference());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
|
@ -1976,37 +1976,9 @@ public class CPPVisitor extends ASTQueries {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static boolean isLValueReference(IType t) {
|
||||||
* [3.10] Lvalues and Rvalues
|
t= SemanticUtil.getNestedType(t, TDEF);
|
||||||
* @param exp
|
return t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference();
|
||||||
* @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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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.CVQualifier._;
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
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.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
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.ICPPPointerToMemberType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
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.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.ArithmeticConversion;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
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.CPPPointerType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
|
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.dom.parser.cpp.semantics.Cost.Rank;
|
||||||
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.ReferenceBinding;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Routines for calculating the cost of conversions.
|
* Routines for calculating the cost of conversions.
|
||||||
*/
|
*/
|
||||||
public class Conversions {
|
public class Conversions {
|
||||||
enum UDCMode {allowUDC, noUDC, deferUDC}
|
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
|
* Computes the cost of an implicit conversion sequence
|
||||||
* [over.best.ics] 13.3.3.1
|
* [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 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
|
* @return the cost of converting from source to target
|
||||||
* @throws DOMException
|
* @throws DOMException
|
||||||
*/
|
*/
|
||||||
public static Cost checkImplicitConversionSequence(boolean sourceIsLValue, IType source,
|
public static Cost checkImplicitConversionSequence(IType target, IType exprType,
|
||||||
IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
|
boolean exprIsLValue, UDCMode udc, boolean isImpliedObjectType) throws DOMException {
|
||||||
if (isImpliedObject) {
|
if (isImpliedObjectType) {
|
||||||
udc= UDCMode.noUDC;
|
udc= UDCMode.noUDC;
|
||||||
}
|
}
|
||||||
|
|
||||||
target= getNestedType(target, TDEF);
|
target= getNestedType(target, TDEF);
|
||||||
source= getNestedType(source, TDEF);
|
exprType= getNestedType(exprType, TDEF | REF);
|
||||||
|
|
||||||
if (target instanceof ICPPReferenceType) {
|
if (target instanceof ICPPReferenceType) {
|
||||||
// [8.5.3-5] initialization of a reference
|
// [8.5.3-5] initialization of a reference
|
||||||
IType cv1T1= getNestedType(target, TDEF | REF);
|
final boolean isLValueRef= !((ICPPReferenceType) target).isRValueReference();
|
||||||
|
final IType cv1T1= getNestedType(target, TDEF | REF);
|
||||||
if (source instanceof ICPPReferenceType) {
|
final IType T1= getNestedType(cv1T1, TDEF | REF | ALLCVQ);
|
||||||
sourceIsLValue= true;
|
final IType cv2T2= exprType;
|
||||||
source= getNestedType(source, TDEF | REF);
|
final IType T2= getNestedType(cv2T2, TDEF | REF | ALLCVQ);
|
||||||
}
|
|
||||||
|
|
||||||
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,"
|
final boolean isImplicitWithoutRefQualifier = isImpliedObjectType; // mstodo need to pass this information to here
|
||||||
if (sourceIsLValue) {
|
ReferenceBinding refBindingType= ReferenceBinding.OTHER;
|
||||||
Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject);
|
if (!isImplicitWithoutRefQualifier) {
|
||||||
if (cost != null) {
|
if (isLValueRef) {
|
||||||
// [8.5.3-5] this is a direct reference binding
|
refBindingType= ReferenceBinding.LVALUE_REF;
|
||||||
// [13.3.3.1.4-1] direct binding has either identity or conversion rank.
|
} else if (exprIsLValue) {
|
||||||
if (cost.getInheritanceDistance() > 0) {
|
refBindingType= ReferenceBinding.RVALUE_REF_BINDS_RVALUE;
|
||||||
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 (operatorCost != null && !ambiguousConversionOperator) {
|
|
||||||
if (isImpliedObject) {
|
|
||||||
operatorCost.setInheritanceDistance(0);
|
|
||||||
}
|
|
||||||
return operatorCost;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// [8.5.3-5] Direct binding failed - Otherwise
|
|
||||||
boolean cv1isConst= getCVQualifier(cv1T1) == CVQualifier.c;
|
// If the reference is an lvalue reference and ...
|
||||||
if (cv1isConst) {
|
if (isLValueRef) {
|
||||||
if (!sourceIsLValue && T2 instanceof ICPPClassType) {
|
// ... the initializer expression is an lvalue (but is not a bit field)
|
||||||
Cost cost= isReferenceCompatible(cv1T1, source, isImpliedObject);
|
// [for overload resolution bit-fields are treated the same, error if selected as best match]
|
||||||
if (cost != null)
|
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;
|
return cost;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// ... or has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be
|
||||||
// 5 - Otherwise
|
// implicitly converted to an lvalue of type “cv3 T3,” where “cv1 T1” is reference-compatible with
|
||||||
// Otherwise, a temporary of type "cv1 T1" is created and initialized from
|
// “cv3 T3” (this conversion is selected by enumerating the applicable conversion functions (13.3.1.6)
|
||||||
// the initializer expression using the rules for a non-reference copy
|
// and choosing the best one through overload resolution (13.3)),
|
||||||
// initialization (8.5). The reference is then bound to the temporary.
|
if (T2 instanceof ICPPClassType && udc != UDCMode.noUDC && isReferenceRelated(T1, T2) < 0) {
|
||||||
|
Cost cost= conversionFuncForDirectReference(cv1T1, cv2T2, T2, true);
|
||||||
// If T1 is reference-related to T2, cv1 must be the same cv-qualification as,
|
if (cost != null) {
|
||||||
// or greater cv-qualification than, cv2; otherwise, the program is ill-formed.
|
cost.setReferenceBinding(refBindingType);
|
||||||
|
return cost;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Cost(source, cv1T1, Rank.NO_MATCH);
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// — 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 (!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(exprType, cv1T1, Rank.NO_MATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-reference binding
|
// Non-reference binding
|
||||||
IType uqsource= getNestedType(source, TDEF | REF | ALLCVQ);
|
IType uqsource= getNestedType(exprType, TDEF | REF | ALLCVQ);
|
||||||
IType uqtarget= getNestedType(target, TDEF | REF | ALLCVQ);
|
IType uqtarget= getNestedType(target, TDEF | REF | ALLCVQ);
|
||||||
|
|
||||||
// [13.3.3.1-6] Derived to base conversion
|
// [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 {
|
private static Cost nonReferenceConversion(boolean sourceIsLValue, IType source, IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
|
||||||
// [13.3.3.1-6] Subsume cv-qualifications
|
// [13.3.3.1-6] Subsume cv-qualifications
|
||||||
IType uqSource= SemanticUtil.getNestedType(source, TDEF | ALLCVQ);
|
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)
|
if (cost.getRank() != Rank.NO_MATCH || udc == UDCMode.noUDC)
|
||||||
return cost;
|
return cost;
|
||||||
|
|
||||||
|
@ -327,10 +407,10 @@ public class Conversions {
|
||||||
* base conversion does not cause any costs.
|
* base conversion does not cause any costs.
|
||||||
* @throws DOMException
|
* @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 {
|
boolean isImplicitThis) throws DOMException {
|
||||||
final Cost cost= new Cost(source, target, Rank.IDENTITY);
|
final Cost cost= new Cost(source, target, Rank.IDENTITY);
|
||||||
if (lvalue_to_rvalue(cost))
|
if (lvalue_to_rvalue(cost, isLValue))
|
||||||
return cost;
|
return cost;
|
||||||
|
|
||||||
if (promotion(cost))
|
if (promotion(cost))
|
||||||
|
@ -370,25 +450,25 @@ public class Conversions {
|
||||||
|
|
||||||
// 13.3.1.4 Copy initialization of class by user-defined conversion
|
// 13.3.1.4 Copy initialization of class by user-defined conversion
|
||||||
if (t instanceof ICPPClassType) {
|
if (t instanceof ICPPClassType) {
|
||||||
Cost cost1= null;
|
FunctionCost cost1= null;
|
||||||
Cost cost2= null;
|
Cost cost2= null;
|
||||||
ICPPConstructor[] ctors= ((ICPPClassType) t).getConstructors();
|
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) {
|
for (ICPPConstructor ctor : ctors) {
|
||||||
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
|
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
|
||||||
final ICPPFunctionType ft = ctor.getType();
|
final ICPPFunctionType ft = ctor.getType();
|
||||||
final IType[] ptypes = ft.getParameterTypes();
|
final IType[] ptypes = ft.getParameterTypes();
|
||||||
Cost c1;
|
FunctionCost c1;
|
||||||
if (ptypes.length == 0) {
|
if (ptypes.length == 0) {
|
||||||
if (ctor.takesVarArgs()) {
|
if (ctor.takesVarArgs()) {
|
||||||
c1= new Cost(source, null, Rank.ELLIPSIS_CONVERSION);
|
c1= new FunctionCost(ctor, new Cost(source, null, Rank.ELLIPSIS_CONVERSION));
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IType ptype= ptypes[0];
|
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)
|
if (ptype instanceof ICPPBasicType && ((ICPPBasicType) ptype).getKind() == Kind.eVoid)
|
||||||
continue;
|
continue;
|
||||||
if (ptypes.length > 1) {
|
if (ptypes.length > 1) {
|
||||||
|
@ -397,9 +477,9 @@ public class Conversions {
|
||||||
continue;
|
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) {
|
if (cmp <= 0) {
|
||||||
cost1= c1;
|
cost1= c1;
|
||||||
cost2= new Cost(t, t, Rank.IDENTITY);
|
cost2= new Cost(t, t, Rank.IDENTITY);
|
||||||
|
@ -421,25 +501,28 @@ public class Conversions {
|
||||||
if (dist >= 0) {
|
if (dist >= 0) {
|
||||||
final ICPPFunctionType ft = op.getType();
|
final ICPPFunctionType ft = op.getType();
|
||||||
IType implicitType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile());
|
IType implicitType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile());
|
||||||
Cost c1= checkImplicitConversionSequence(sourceIsLValue, source, implicitType, UDCMode.noUDC, false);
|
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
|
||||||
int cmp= c1.compareTo(cost1);
|
if (udcCost != null) {
|
||||||
if (cmp <= 0) {
|
FunctionCost c1= new FunctionCost(op, udcCost);
|
||||||
cost1= c1;
|
int cmp= c1.compareTo(null, cost1);
|
||||||
cost2= new Cost(t, t, Rank.IDENTITY);
|
if (cmp <= 0) {
|
||||||
if (dist > 0) {
|
cost1= c1;
|
||||||
cost2.setInheritanceDistance(dist);
|
cost2= new Cost(t, t, Rank.IDENTITY);
|
||||||
cost2.setRank(Rank.CONVERSION);
|
if (dist > 0) {
|
||||||
}
|
cost2.setInheritanceDistance(dist);
|
||||||
cost2.setUserDefinedConversion(op);
|
cost2.setRank(Rank.CONVERSION);
|
||||||
if (cmp == 0) {
|
}
|
||||||
cost2.setAmbiguousUDC(true);
|
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 null;
|
||||||
|
|
||||||
return cost2;
|
return cost2;
|
||||||
|
@ -449,30 +532,35 @@ public class Conversions {
|
||||||
if (s instanceof ICPPClassType) {
|
if (s instanceof ICPPClassType) {
|
||||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
|
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
|
||||||
CPPTemplates.instantiateConversionTemplates(ops, target);
|
CPPTemplates.instantiateConversionTemplates(ops, target);
|
||||||
Cost cost1= null;
|
FunctionCost cost1= null;
|
||||||
Cost cost2= null;
|
Cost cost2= null;
|
||||||
for (final ICPPMethod op : ops) {
|
for (final ICPPMethod op : ops) {
|
||||||
if (op != null && !(op instanceof IProblemBinding)) {
|
if (op != null && !(op instanceof IProblemBinding)) {
|
||||||
final IType returnType = op.getType().getReturnType();
|
final IType returnType = op.getType().getReturnType();
|
||||||
IType uqReturnType= getNestedType(returnType, TDEF | ALLCVQ);
|
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) {
|
if (c2.getRank() != Rank.NO_MATCH) {
|
||||||
ICPPFunctionType ftype = op.getType();
|
ICPPFunctionType ftype = op.getType();
|
||||||
IType implicitType= CPPSemantics.getImplicitType(op, ftype.isConst(), ftype.isVolatile());
|
IType implicitType= CPPSemantics.getImplicitType(op, ftype.isConst(), ftype.isVolatile());
|
||||||
Cost c1= checkImplicitConversionSequence(sourceIsLValue, source, implicitType, UDCMode.noUDC, false);
|
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
|
||||||
int cmp= c1.compareTo(cost1);
|
if (udcCost != null) {
|
||||||
if (cmp <= 0) {
|
FunctionCost c1= new FunctionCost(op, udcCost);
|
||||||
cost1= c1;
|
int cmp= c1.compareTo(null, cost1);
|
||||||
cost2= c2;
|
if (cmp <= 0) {
|
||||||
cost2.setUserDefinedConversion(op);
|
cost1= c1;
|
||||||
if (cmp == 0) {
|
cost2= c2;
|
||||||
cost2.setAmbiguousUDC(true);
|
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 null;
|
||||||
|
|
||||||
return cost2;
|
return cost2;
|
||||||
|
@ -511,7 +599,6 @@ public class Conversions {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tbase= getNestedType(tbase, TDEF);
|
|
||||||
if (tbase instanceof ICPPClassType) {
|
if (tbase instanceof ICPPClassType) {
|
||||||
int n= calculateInheritanceDepth(maxdepth - 1, tbase, ancestorToFind);
|
int n= calculateInheritanceDepth(maxdepth - 1, tbase, ancestorToFind);
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
|
@ -531,38 +618,31 @@ public class Conversions {
|
||||||
* [4.2] array-to-ptr
|
* [4.2] array-to-ptr
|
||||||
* [4.3] function-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.
|
// target should not be a reference here.
|
||||||
boolean isConverted= false;
|
boolean isConverted= false;
|
||||||
IType target = getNestedType(cost.target, REF | TDEF);
|
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
|
// 4.1 lvalue to rvalue
|
||||||
IType srcRValue= getNestedType(source, REF | TDEF);
|
if (isLValue) {
|
||||||
if (source instanceof ICPPReferenceType) {
|
|
||||||
// 4.1 lvalue of non-function and non-array
|
// 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
|
// 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 (unqualifiedSrcRValue instanceof ICPPClassType) {
|
||||||
if (isCompleteType(unqualifiedSrcRValue)) {
|
cost.setRank(Rank.NO_MATCH);
|
||||||
source= srcRValue;
|
return true;
|
||||||
} else {
|
|
||||||
// ill-formed
|
|
||||||
cost.setRank(Rank.NO_MATCH);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
source= unqualifiedSrcRValue;
|
source= unqualifiedSrcRValue;
|
||||||
}
|
}
|
||||||
cost.setRank(Rank.LVALUE_TRANSFORMATION);
|
|
||||||
isConverted= true;
|
isConverted= true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4.2 array to pointer conversion
|
// 4.2 array to pointer conversion
|
||||||
if (!isConverted && srcRValue instanceof IArrayType) {
|
if (!isConverted && source instanceof IArrayType) {
|
||||||
final IArrayType arrayType= (IArrayType) srcRValue;
|
final IArrayType arrayType= (IArrayType) source;
|
||||||
|
|
||||||
if (target instanceof IPointerType) {
|
if (target instanceof IPointerType) {
|
||||||
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
|
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
|
||||||
|
@ -579,7 +659,6 @@ public class Conversions {
|
||||||
if (lit.getKind() == IASTLiteralExpression.lk_string_literal) {
|
if (lit.getKind() == IASTLiteralExpression.lk_string_literal) {
|
||||||
source= new CPPPointerType(tmp, false, false);
|
source= new CPPPointerType(tmp, false, false);
|
||||||
cost.setQualificationAdjustment(getCVQualifier(targetPtrTgt).isVolatile() ? 2 : 1);
|
cost.setQualificationAdjustment(getCVQualifier(targetPtrTgt).isVolatile() ? 2 : 1);
|
||||||
cost.setRank(Rank.LVALUE_TRANSFORMATION);
|
|
||||||
isConverted= true;
|
isConverted= true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -589,7 +668,6 @@ public class Conversions {
|
||||||
}
|
}
|
||||||
if (!isConverted && (target instanceof IPointerType || target instanceof IBasicType)) {
|
if (!isConverted && (target instanceof IPointerType || target instanceof IBasicType)) {
|
||||||
source = new CPPPointerType(getNestedType(arrayType.getType(), TDEF));
|
source = new CPPPointerType(getNestedType(arrayType.getType(), TDEF));
|
||||||
cost.setRank(Rank.LVALUE_TRANSFORMATION);
|
|
||||||
isConverted= true;
|
isConverted= true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -597,9 +675,8 @@ public class Conversions {
|
||||||
// 4.3 function to pointer conversion
|
// 4.3 function to pointer conversion
|
||||||
if (!isConverted && target instanceof IPointerType) {
|
if (!isConverted && target instanceof IPointerType) {
|
||||||
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
|
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);
|
source = new CPPPointerType(source);
|
||||||
cost.setRank(Rank.LVALUE_TRANSFORMATION);
|
|
||||||
isConverted= true;
|
isConverted= true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -849,30 +926,4 @@ public class Conversions {
|
||||||
}
|
}
|
||||||
return false;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,12 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
*/
|
*/
|
||||||
final class Cost {
|
final class Cost {
|
||||||
enum Rank {
|
enum Rank {
|
||||||
IDENTITY, LVALUE_TRANSFORMATION, PROMOTION, CONVERSION, CONVERSION_PTR_BOOL,
|
IDENTITY, PROMOTION, CONVERSION, CONVERSION_PTR_BOOL,
|
||||||
USER_DEFINED_CONVERSION, ELLIPSIS_CONVERSION, NO_MATCH
|
USER_DEFINED_CONVERSION, ELLIPSIS_CONVERSION, NO_MATCH
|
||||||
}
|
}
|
||||||
|
enum ReferenceBinding {
|
||||||
|
RVALUE_REF_BINDS_RVALUE, LVALUE_REF, OTHER
|
||||||
|
}
|
||||||
|
|
||||||
IType source;
|
IType source;
|
||||||
IType target;
|
IType target;
|
||||||
|
@ -38,11 +41,13 @@ final class Cost {
|
||||||
private int fQualificationAdjustments;
|
private int fQualificationAdjustments;
|
||||||
private int fInheritanceDistance;
|
private int fInheritanceDistance;
|
||||||
private ICPPFunction fUserDefinedConversion;
|
private ICPPFunction fUserDefinedConversion;
|
||||||
|
private ReferenceBinding fReferenceBinding;
|
||||||
|
|
||||||
public Cost(IType s, IType t, Rank rank) {
|
public Cost(IType s, IType t, Rank rank) {
|
||||||
source = s;
|
source = s;
|
||||||
target = t;
|
target = t;
|
||||||
fRank= rank;
|
fRank= rank;
|
||||||
|
fReferenceBinding= ReferenceBinding.OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rank getRank() {
|
public Rank getRank() {
|
||||||
|
@ -53,6 +58,11 @@ final class Cost {
|
||||||
fRank= rank;
|
fRank= rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setReferenceBinding(ReferenceBinding binding) {
|
||||||
|
fReferenceBinding= binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isAmbiguousUDC() {
|
public boolean isAmbiguousUDC() {
|
||||||
return fAmbiguousUDC;
|
return fAmbiguousUDC;
|
||||||
}
|
}
|
||||||
|
@ -79,9 +89,6 @@ final class Cost {
|
||||||
|
|
||||||
public void setQualificationAdjustment(int adjustment) {
|
public void setQualificationAdjustment(int adjustment) {
|
||||||
fQualificationAdjustments= adjustment;
|
fQualificationAdjustments= adjustment;
|
||||||
if (adjustment != 0 && fRank == Rank.IDENTITY) {
|
|
||||||
fRank= Rank.LVALUE_TRANSFORMATION;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,13 +137,21 @@ final class Cost {
|
||||||
if (cmp != 0)
|
if (cmp != 0)
|
||||||
return cmp;
|
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;
|
int qdiff= fQualificationAdjustments ^ other.fQualificationAdjustments;
|
||||||
if (qdiff != 0) {
|
if (qdiff != 0) {
|
||||||
if ((fQualificationAdjustments & qdiff) == 0)
|
if ((fQualificationAdjustments & qdiff) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
if ((other.fQualificationAdjustments & qdiff) == 0)
|
if ((other.fQualificationAdjustments & qdiff) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,12 @@ class FunctionCost {
|
||||||
fSourceIsLValue= new BitSet(paramCount);
|
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() {
|
public int getLength() {
|
||||||
return fCosts.length;
|
return fCosts.length;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
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.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.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
||||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
||||||
|
@ -108,6 +110,7 @@ public class LookupData {
|
||||||
private Object[] functionArgs;
|
private Object[] functionArgs;
|
||||||
private IType[] functionArgTypes;
|
private IType[] functionArgTypes;
|
||||||
public ProblemBinding problem;
|
public ProblemBinding problem;
|
||||||
|
private BitSet functionArgLValues;
|
||||||
|
|
||||||
public LookupData(IASTName n) {
|
public LookupData(IASTName n) {
|
||||||
astName = n;
|
astName = n;
|
||||||
|
@ -600,7 +603,7 @@ public class LookupData {
|
||||||
functionArgTypes= new IType[pdecls.length];
|
functionArgTypes= new IType[pdecls.length];
|
||||||
for (int i = 0; i < pdecls.length; i++) {
|
for (int i = 0; i < pdecls.length; i++) {
|
||||||
IASTParameterDeclaration p = pdecls[i];
|
IASTParameterDeclaration p = pdecls[i];
|
||||||
functionArgTypes[i]= CPPVisitor.createType(p.getDeclarator());
|
functionArgTypes[i]= SemanticUtil.getSimplifiedType(CPPVisitor.createType(p.getDeclarator()));
|
||||||
}
|
}
|
||||||
} else if (functionArgs instanceof IASTExpression[]) {
|
} else if (functionArgs instanceof IASTExpression[]) {
|
||||||
IASTExpression[] exprs= (IASTExpression[]) functionArgs;
|
IASTExpression[] exprs= (IASTExpression[]) functionArgs;
|
||||||
|
@ -608,13 +611,37 @@ public class LookupData {
|
||||||
for (int i = 0; i < exprs.length; i++) {
|
for (int i = 0; i < exprs.length; i++) {
|
||||||
IASTExpression e = exprs[i];
|
IASTExpression e = exprs[i];
|
||||||
IType etype= e.getExpressionType();
|
IType etype= e.getExpressionType();
|
||||||
functionArgTypes[i]= etype;
|
functionArgTypes[i]= SemanticUtil.getSimplifiedType(etype);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return functionArgTypes;
|
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) {
|
public void setFunctionArgumentTypes(IType[] paramTypes) {
|
||||||
functionArgTypes= paramTypes;
|
functionArgTypes= paramTypes;
|
||||||
|
|
|
@ -275,8 +275,18 @@ public class SemanticUtil {
|
||||||
return type;
|
return type;
|
||||||
return replaceNestedType((ITypeContainer) atype, newNested);
|
return replaceNestedType((ITypeContainer) atype, newNested);
|
||||||
}
|
}
|
||||||
} else if ((options & REF) != 0 && type instanceof ICPPReferenceType) {
|
} else if (type instanceof ICPPReferenceType) {
|
||||||
t= ((ICPPReferenceType) type).getType();
|
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)
|
if (t == null)
|
||||||
return type;
|
return type;
|
||||||
|
@ -323,6 +333,28 @@ public class SemanticUtil {
|
||||||
}
|
}
|
||||||
return type;
|
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) {
|
public static IType replaceNestedType(ITypeContainer type, IType newNestedType) {
|
||||||
if (newNestedType == null)
|
if (newNestedType == null)
|
||||||
|
|
|
@ -161,7 +161,7 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
||||||
IType r= rt.getType();
|
IType r= rt.getType();
|
||||||
IType r2= getCompositeType(r);
|
IType r2= getCompositeType(r);
|
||||||
if (r != r2) {
|
if (r != r2) {
|
||||||
return new CPPReferenceType(r2);
|
return new CPPReferenceType(r2, rt.isRValueReference());
|
||||||
}
|
}
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,7 @@ public class NodeContainer {
|
||||||
declarator.addPointerOperator(new CASTPointer());
|
declarator.addPointerOperator(new CASTPointer());
|
||||||
break;
|
break;
|
||||||
case CPP:
|
case CPP:
|
||||||
declarator.addPointerOperator(new CPPASTReferenceOperator());
|
declarator.addPointerOperator(new CPPASTReferenceOperator(false));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -11,7 +11,6 @@
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.upc.ast;
|
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.ASTVisitor;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||||
import org.eclipse.cdt.core.dom.upc.ast.IUPCASTKeywordExpression;
|
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);
|
return new CBasicType(Kind.eInt, 0, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(ASTVisitor visitor) {
|
public boolean accept(ASTVisitor visitor) {
|
||||||
if(visitor.shouldVisitExpressions) {
|
if(visitor.shouldVisitExpressions) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue