mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-02 22:05:44 +02:00
Bug 324853: Expression type for conditional expression.
This commit is contained in:
parent
c5aee0fe78
commit
4c1d5c5347
9 changed files with 603 additions and 186 deletions
|
@ -18,6 +18,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.XVALUE;
|
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.XVALUE;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -272,6 +273,15 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
return tu;
|
return tu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected IASTTranslationUnit parseAndCheckBindings() throws Exception {
|
||||||
|
String code= getAboveComment();
|
||||||
|
return parseAndCheckBindings(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BindingAssertionHelper getAssertionHelper() throws ParserException, IOException {
|
||||||
|
String code= getAboveComment();
|
||||||
|
return new BindingAssertionHelper(code, true);
|
||||||
|
}
|
||||||
|
|
||||||
public void testBug40422() throws Exception
|
public void testBug40422() throws Exception
|
||||||
{
|
{
|
||||||
|
@ -4543,7 +4553,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// };
|
// };
|
||||||
// Sub::Sub( Other * b ) : Base(b) {}
|
// Sub::Sub( Other * b ) : Base(b) {}
|
||||||
public void testBug95673() throws Exception {
|
public void testBug95673() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
|
|
||||||
ICPPConstructor ctor= ba.assertNonProblem("Base( Other", 4, ICPPConstructor.class);
|
ICPPConstructor ctor= ba.assertNonProblem("Base( Other", 4, ICPPConstructor.class);
|
||||||
ICPPConstructor ctor2= ba.assertNonProblem("Base(b)", 4, ICPPConstructor.class);
|
ICPPConstructor ctor2= ba.assertNonProblem("Base(b)", 4, ICPPConstructor.class);
|
||||||
|
@ -4949,7 +4959,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// f1(__null);
|
// f1(__null);
|
||||||
// }
|
// }
|
||||||
public void testBug240567() throws Exception {
|
public void testBug240567() throws Exception {
|
||||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
bh.assertNonProblem("f1(__null", 2, ICPPFunction.class);
|
bh.assertNonProblem("f1(__null", 2, ICPPFunction.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5298,7 +5308,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// problem5(ptm);
|
// problem5(ptm);
|
||||||
// }
|
// }
|
||||||
public void testBug214335() throws Exception {
|
public void testBug214335() throws Exception {
|
||||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
|
|
||||||
IBinding b00= bh.assertProblem("problem1(\"", 8);
|
IBinding b00= bh.assertProblem("problem1(\"", 8);
|
||||||
IBinding b01= bh.assertProblem("problem2(\"", 8);
|
IBinding b01= bh.assertProblem("problem2(\"", 8);
|
||||||
|
@ -5416,7 +5426,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// a=0;
|
// a=0;
|
||||||
// }
|
// }
|
||||||
public void testUsingDirectiveWithNestedClass_Bug209582() throws Exception {
|
public void testUsingDirectiveWithNestedClass_Bug209582() throws Exception {
|
||||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
|
|
||||||
IBinding b= bh.assertNonProblem("a=", 1);
|
IBinding b= bh.assertNonProblem("a=", 1);
|
||||||
assertEquals("x", b.getScope().getScopeName().toString());
|
assertEquals("x", b.getScope().getScopeName().toString());
|
||||||
|
@ -5435,7 +5445,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// Test foo3 (&bar);
|
// Test foo3 (&bar);
|
||||||
// }
|
// }
|
||||||
public void testCastAmbiguity_Bug211756() throws Exception {
|
public void testCastAmbiguity_Bug211756() throws Exception {
|
||||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
|
|
||||||
bh.assertNonProblem("foo1", 4);
|
bh.assertNonProblem("foo1", 4);
|
||||||
bh.assertNonProblem("foo2", 4);
|
bh.assertNonProblem("foo2", 4);
|
||||||
|
@ -5449,7 +5459,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// return 0;
|
// return 0;
|
||||||
// }
|
// }
|
||||||
public void testTemplateIDAmbiguity_Bug104706() throws Exception {
|
public void testTemplateIDAmbiguity_Bug104706() throws Exception {
|
||||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
|
|
||||||
bh.assertNonProblem("relayIndex <", 10);
|
bh.assertNonProblem("relayIndex <", 10);
|
||||||
bh.assertNonProblem("relayIndex >", 10);
|
bh.assertNonProblem("relayIndex >", 10);
|
||||||
|
@ -5487,7 +5497,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// func(unqualified);
|
// func(unqualified);
|
||||||
// }
|
// }
|
||||||
public void testScopeOfUsingDelegates_Bug219424() throws Exception {
|
public void testScopeOfUsingDelegates_Bug219424() throws Exception {
|
||||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
|
|
||||||
bh.assertNonProblem("cl c", 2);
|
bh.assertNonProblem("cl c", 2);
|
||||||
bh.assertNonProblem("func(qualified)", 4);
|
bh.assertNonProblem("func(qualified)", 4);
|
||||||
|
@ -5593,7 +5603,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
|
|
||||||
// namespace ns { typedef int ns::TINT; } // illegal, still no CCE is expected.
|
// namespace ns { typedef int ns::TINT; } // illegal, still no CCE is expected.
|
||||||
public void testQualifiedTypedefs_Bug222093() throws Exception{
|
public void testQualifiedTypedefs_Bug222093() throws Exception{
|
||||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
IBinding td= bh.assertProblem("TINT", 4);
|
IBinding td= bh.assertProblem("TINT", 4);
|
||||||
bh.assertProblem("ns::", 2);
|
bh.assertProblem("ns::", 2);
|
||||||
}
|
}
|
||||||
|
@ -5667,7 +5677,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// foo/*k2*/(11.1E1L);
|
// foo/*k2*/(11.1E1L);
|
||||||
// }
|
// }
|
||||||
public void testLiteralsViaOverloads_225534() throws Exception {
|
public void testLiteralsViaOverloads_225534() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
char[] cs= {'a','b','e','f','g','h','i','j','k'};
|
char[] cs= {'a','b','e','f','g','h','i','j','k'};
|
||||||
for(char c : cs) {
|
for(char c : cs) {
|
||||||
for(int i=1; i<(c < 'i' ? 4 : 3); i++) {
|
for(int i=1; i<(c < 'i' ? 4 : 3); i++) {
|
||||||
|
@ -5727,7 +5737,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// X::operator int() {}
|
// X::operator int() {}
|
||||||
// X::xtint(a); // 2
|
// X::xtint(a); // 2
|
||||||
public void testEmptyDeclSpecifier() throws Exception {
|
public void testEmptyDeclSpecifier() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("X {", 1, ICPPClassType.class);
|
ba.assertNonProblem("X {", 1, ICPPClassType.class);
|
||||||
ba.assertNonProblem("X()", 1, ICPPConstructor.class);
|
ba.assertNonProblem("X()", 1, ICPPConstructor.class);
|
||||||
ba.assertNonProblem("~X", 2, ICPPMethod.class);
|
ba.assertNonProblem("~X", 2, ICPPMethod.class);
|
||||||
|
@ -5832,7 +5842,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// class C;
|
// class C;
|
||||||
// void func(void (C::*m)(int) const);
|
// void func(void (C::*m)(int) const);
|
||||||
public void test233889_a() throws Exception {
|
public void test233889_a() throws Exception {
|
||||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
ICPPFunction func= bh.assertNonProblem("func(", 4, ICPPFunction.class);
|
ICPPFunction func= bh.assertNonProblem("func(", 4, ICPPFunction.class);
|
||||||
assertEquals(1,func.getParameters().length);
|
assertEquals(1,func.getParameters().length);
|
||||||
IType type= func.getParameters()[0].getType();
|
IType type= func.getParameters()[0].getType();
|
||||||
|
@ -5854,7 +5864,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// func(&C::m2);
|
// func(&C::m2);
|
||||||
// }
|
// }
|
||||||
public void testBug233889_b() throws Exception {
|
public void testBug233889_b() throws Exception {
|
||||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
ICPPFunction fn1= bh.assertNonProblem("func(&C::m1", 4, ICPPFunction.class);
|
ICPPFunction fn1= bh.assertNonProblem("func(&C::m1", 4, ICPPFunction.class);
|
||||||
ICPPFunction fn2= bh.assertNonProblem("func(&C::m2", 4, ICPPFunction.class);
|
ICPPFunction fn2= bh.assertNonProblem("func(&C::m2", 4, ICPPFunction.class);
|
||||||
assertNotSame(fn1, fn2);
|
assertNotSame(fn1, fn2);
|
||||||
|
@ -5875,7 +5885,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// void member4() const volatile { foo(this);/*4*/ }
|
// void member4() const volatile { foo(this);/*4*/ }
|
||||||
// };
|
// };
|
||||||
public void testThisType() throws Exception {
|
public void testThisType() throws Exception {
|
||||||
BindingAssertionHelper ba=new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba=getAssertionHelper();
|
||||||
ICPPFunction pt1= ba.assertNonProblem("foo(this);/*1*/", 3, ICPPFunction.class);
|
ICPPFunction pt1= ba.assertNonProblem("foo(this);/*1*/", 3, ICPPFunction.class);
|
||||||
ICPPFunction pt2= ba.assertNonProblem("foo(this);/*2*/", 3, ICPPFunction.class);
|
ICPPFunction pt2= ba.assertNonProblem("foo(this);/*2*/", 3, ICPPFunction.class);
|
||||||
ICPPFunction pt3= ba.assertNonProblem("foo(this);/*3*/", 3, ICPPFunction.class);
|
ICPPFunction pt3= ba.assertNonProblem("foo(this);/*3*/", 3, ICPPFunction.class);
|
||||||
|
@ -5904,7 +5914,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// a2->foo();/*2*/
|
// a2->foo();/*2*/
|
||||||
// }
|
// }
|
||||||
public void testMemberAccessOperator_a() throws Exception {
|
public void testMemberAccessOperator_a() throws Exception {
|
||||||
BindingAssertionHelper ba=new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba=getAssertionHelper();
|
||||||
ba.assertProblem("foo();/*1*/", 3);
|
ba.assertProblem("foo();/*1*/", 3);
|
||||||
ba.assertNonProblem("foo();/*2*/", 3);
|
ba.assertNonProblem("foo();/*2*/", 3);
|
||||||
}
|
}
|
||||||
|
@ -5927,7 +5937,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// b2->foo();/*2*/
|
// b2->foo();/*2*/
|
||||||
// }
|
// }
|
||||||
public void testMemberAccessOperator_b() throws Exception {
|
public void testMemberAccessOperator_b() throws Exception {
|
||||||
BindingAssertionHelper ba=new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba=getAssertionHelper();
|
||||||
ICPPMethod m1= ba.assertNonProblem("foo();/*1*/", 3, ICPPMethod.class);
|
ICPPMethod m1= ba.assertNonProblem("foo();/*1*/", 3, ICPPMethod.class);
|
||||||
ICPPMethod m2= ba.assertNonProblem("foo();/*2*/", 3, ICPPMethod.class);
|
ICPPMethod m2= ba.assertNonProblem("foo();/*2*/", 3, ICPPMethod.class);
|
||||||
assertEquals(m1.getClassOwner().getName(), "A");
|
assertEquals(m1.getClassOwner().getName(), "A");
|
||||||
|
@ -5943,7 +5953,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// c->foo();/**/ // refers to A::foo
|
// c->foo();/**/ // refers to A::foo
|
||||||
// }
|
// }
|
||||||
public void testMemberAccessOperator_c() throws Exception {
|
public void testMemberAccessOperator_c() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("foo();/**/", 3);
|
ba.assertNonProblem("foo();/**/", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5956,7 +5966,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// c->foo();/**/ // expect problem - foo is not in B
|
// c->foo();/**/ // expect problem - foo is not in B
|
||||||
// }
|
// }
|
||||||
public void testMemberAccessOperator_d() throws Exception {
|
public void testMemberAccessOperator_d() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertProblem("foo();/**/", 3);
|
ba.assertProblem("foo();/**/", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5972,7 +5982,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// c->foo();/**/ // refers to A::foo
|
// c->foo();/**/ // refers to A::foo
|
||||||
// }
|
// }
|
||||||
public void testMemberAccessOperator_e() throws Exception {
|
public void testMemberAccessOperator_e() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("foo();/**/", 3);
|
ba.assertNonProblem("foo();/**/", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6000,7 +6010,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// f4(s);
|
// f4(s);
|
||||||
// }
|
// }
|
||||||
public void testArrayToPointerConversion() throws Exception {
|
public void testArrayToPointerConversion() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("f1(p)", 2, ICPPFunction.class);
|
ba.assertNonProblem("f1(p)", 2, ICPPFunction.class);
|
||||||
ba.assertProblem("f2(q)", 2);
|
ba.assertProblem("f2(q)", 2);
|
||||||
ba.assertNonProblem("f3(r)", 2, ICPPFunction.class);
|
ba.assertNonProblem("f3(r)", 2, ICPPFunction.class);
|
||||||
|
@ -6100,7 +6110,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// func(y);
|
// func(y);
|
||||||
// }
|
// }
|
||||||
public void testOverloadedFunction_248774() throws Exception {
|
public void testOverloadedFunction_248774() throws Exception {
|
||||||
BindingAssertionHelper helper= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper helper= getAssertionHelper();
|
||||||
ICPPFunction func1= helper.assertNonProblem("func(x)", 4, ICPPFunction.class);
|
ICPPFunction func1= helper.assertNonProblem("func(x)", 4, ICPPFunction.class);
|
||||||
ICPPFunction func2= helper.assertNonProblem("func(y)", 4, ICPPFunction.class);
|
ICPPFunction func2= helper.assertNonProblem("func(y)", 4, ICPPFunction.class);
|
||||||
assertNotSame(func1, func2);
|
assertNotSame(func1, func2);
|
||||||
|
@ -6119,7 +6129,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// func(y[0]);
|
// func(y[0]);
|
||||||
// }
|
// }
|
||||||
public void testOverloadedOperator_248803() throws Exception {
|
public void testOverloadedOperator_248803() throws Exception {
|
||||||
BindingAssertionHelper helper= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper helper= getAssertionHelper();
|
||||||
ICPPFunction func1= helper.assertNonProblem("func(x[0])", 4, ICPPFunction.class);
|
ICPPFunction func1= helper.assertNonProblem("func(x[0])", 4, ICPPFunction.class);
|
||||||
ICPPFunction func2= helper.assertNonProblem("func(y[0])", 4, ICPPFunction.class);
|
ICPPFunction func2= helper.assertNonProblem("func(y[0])", 4, ICPPFunction.class);
|
||||||
assertNotSame(func1, func2);
|
assertNotSame(func1, func2);
|
||||||
|
@ -6144,7 +6154,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// void m();//5
|
// void m();//5
|
||||||
// };
|
// };
|
||||||
public void testOverridden_248846() throws Exception {
|
public void testOverridden_248846() throws Exception {
|
||||||
BindingAssertionHelper helper= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper helper= getAssertionHelper();
|
||||||
ICPPMethod m0= helper.assertNonProblem("m();//0", 1, ICPPMethod.class);
|
ICPPMethod m0= helper.assertNonProblem("m();//0", 1, ICPPMethod.class);
|
||||||
ICPPMethod m1= helper.assertNonProblem("m();//1", 1, ICPPMethod.class);
|
ICPPMethod m1= helper.assertNonProblem("m();//1", 1, ICPPMethod.class);
|
||||||
ICPPMethod m2= helper.assertNonProblem("m();//2", 1, ICPPMethod.class);
|
ICPPMethod m2= helper.assertNonProblem("m();//2", 1, ICPPMethod.class);
|
||||||
|
@ -6242,7 +6252,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// f(p);
|
// f(p);
|
||||||
// }
|
// }
|
||||||
public void testFunctionExtraArgument() throws Exception {
|
public void testFunctionExtraArgument() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertProblem("f(p)", 1);
|
ba.assertProblem("f(p)", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6367,7 +6377,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// int y;
|
// int y;
|
||||||
// };
|
// };
|
||||||
public void testScopeOfClassMember_259460() throws Exception {
|
public void testScopeOfClassMember_259460() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("B b", 1, ICPPClassType.class);
|
ba.assertNonProblem("B b", 1, ICPPClassType.class);
|
||||||
ba.assertProblem("B p", 1);
|
ba.assertProblem("B p", 1);
|
||||||
ba.assertProblem("B method", 1);
|
ba.assertProblem("B method", 1);
|
||||||
|
@ -6386,7 +6396,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// };
|
// };
|
||||||
// };
|
// };
|
||||||
public void testScopeOfClassMember_259648() throws Exception {
|
public void testScopeOfClassMember_259648() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("GREEN)", 5, IEnumerator.class);
|
ba.assertNonProblem("GREEN)", 5, IEnumerator.class);
|
||||||
ba.assertNonProblem("RED;", 3, IEnumerator.class);
|
ba.assertNonProblem("RED;", 3, IEnumerator.class);
|
||||||
ba.assertProblem("GREEN;", 5);
|
ba.assertProblem("GREEN;", 5);
|
||||||
|
@ -6404,7 +6414,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// func(*b);
|
// func(*b);
|
||||||
// }
|
// }
|
||||||
public void testSmartPointerReference_259680() throws Exception {
|
public void testSmartPointerReference_259680() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ICPPFunction f1= ba.assertNonProblem("func(*a)", 4, ICPPFunction.class);
|
ICPPFunction f1= ba.assertNonProblem("func(*a)", 4, ICPPFunction.class);
|
||||||
ICPPFunction f2= ba.assertNonProblem("func(*b)", 4, ICPPFunction.class);
|
ICPPFunction f2= ba.assertNonProblem("func(*b)", 4, ICPPFunction.class);
|
||||||
assertNotSame(f1, f2);
|
assertNotSame(f1, f2);
|
||||||
|
@ -6445,7 +6455,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// (p1 % p2).a; //5
|
// (p1 % p2).a; //5
|
||||||
// }
|
// }
|
||||||
public void testOverloadedBinaryOperator_259927_1() throws Exception {
|
public void testOverloadedBinaryOperator_259927_1() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("a; //1", 1, ICPPField.class);
|
ba.assertNonProblem("a; //1", 1, ICPPField.class);
|
||||||
ba.assertNonProblem("a; //2", 1, ICPPField.class);
|
ba.assertNonProblem("a; //2", 1, ICPPField.class);
|
||||||
ba.assertNonProblem("a; //3", 1, ICPPField.class);
|
ba.assertNonProblem("a; //3", 1, ICPPField.class);
|
||||||
|
@ -6474,7 +6484,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// (b + i).a; //6
|
// (b + i).a; //6
|
||||||
// }
|
// }
|
||||||
public void testOverloadedBinaryOperator_259927_2() throws Exception {
|
public void testOverloadedBinaryOperator_259927_2() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("a; //1", 1, ICPPField.class);
|
ba.assertNonProblem("a; //1", 1, ICPPField.class);
|
||||||
ba.assertNonProblem("a; //2", 1, ICPPField.class);
|
ba.assertNonProblem("a; //2", 1, ICPPField.class);
|
||||||
ba.assertNonProblem("a; //3", 1, ICPPField.class);
|
ba.assertNonProblem("a; //3", 1, ICPPField.class);
|
||||||
|
@ -6498,7 +6508,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// (++p1).x; //2
|
// (++p1).x; //2
|
||||||
// }
|
// }
|
||||||
public void testOverloadedUnaryOperator_259927_3() throws Exception {
|
public void testOverloadedUnaryOperator_259927_3() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("x; //1", 1, ICPPField.class);
|
ba.assertNonProblem("x; //1", 1, ICPPField.class);
|
||||||
ba.assertNonProblem("x; //2", 1, ICPPField.class);
|
ba.assertNonProblem("x; //2", 1, ICPPField.class);
|
||||||
}
|
}
|
||||||
|
@ -6516,7 +6526,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// (++p1).x; //2
|
// (++p1).x; //2
|
||||||
// }
|
// }
|
||||||
public void testOverloadedUnaryOperator_259927_4() throws Exception {
|
public void testOverloadedUnaryOperator_259927_4() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("x; //1", 1, ICPPField.class);
|
ba.assertNonProblem("x; //1", 1, ICPPField.class);
|
||||||
ba.assertNonProblem("x; //2", 1, ICPPField.class);
|
ba.assertNonProblem("x; //2", 1, ICPPField.class);
|
||||||
}
|
}
|
||||||
|
@ -6547,7 +6557,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// (~b).xx; // 6
|
// (~b).xx; // 6
|
||||||
// }
|
// }
|
||||||
public void testOverloadedUnaryOperator_259927_5() throws Exception {
|
public void testOverloadedUnaryOperator_259927_5() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
for(int i = 1; i <=6; i++)
|
for(int i = 1; i <=6; i++)
|
||||||
ba.assertNonProblem("xx; // "+i, 2, ICPPField.class);
|
ba.assertNonProblem("xx; // "+i, 2, ICPPField.class);
|
||||||
}
|
}
|
||||||
|
@ -6578,7 +6588,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// (~b).xx; // 6
|
// (~b).xx; // 6
|
||||||
//}
|
//}
|
||||||
public void testOverloadedUnaryOperator_259927_6() throws Exception {
|
public void testOverloadedUnaryOperator_259927_6() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
for(int i = 1; i <=6; i++)
|
for(int i = 1; i <=6; i++)
|
||||||
ba.assertNonProblem("xx; // "+i, 2, ICPPField.class);
|
ba.assertNonProblem("xx; // "+i, 2, ICPPField.class);
|
||||||
}
|
}
|
||||||
|
@ -6599,7 +6609,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// typedef int S2 (int(t)); // resolve this ambiguity first
|
// typedef int S2 (int(t)); // resolve this ambiguity first
|
||||||
// };
|
// };
|
||||||
public void testOrderOfAmbiguityResolution_259373() throws Exception {
|
public void testOrderOfAmbiguityResolution_259373() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ICPPVariable a= ba.assertNonProblem("a;", 1);
|
ICPPVariable a= ba.assertNonProblem("a;", 1);
|
||||||
assertInstance(a.getType(), IPointerType.class);
|
assertInstance(a.getType(), IPointerType.class);
|
||||||
ICPPVariable b= ba.assertNonProblem("b;", 1);
|
ICPPVariable b= ba.assertNonProblem("b;", 1);
|
||||||
|
@ -6780,7 +6790,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// f(a());
|
// f(a());
|
||||||
// }
|
// }
|
||||||
public void testBug263152_1() throws Exception {
|
public void testBug263152_1() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertProblem("f(a())", 1);
|
ba.assertProblem("f(a())", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6796,7 +6806,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// p.m(a());
|
// p.m(a());
|
||||||
// }
|
// }
|
||||||
public void testBug263152_2() throws Exception {
|
public void testBug263152_2() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("m(a())", 1, ICPPMethod.class);
|
ba.assertNonProblem("m(a())", 1, ICPPMethod.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6807,7 +6817,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
public void _testInstanceMemberInStaticMethod_263154() throws Exception {
|
public void _testInstanceMemberInStaticMethod_263154() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertProblem("a =", 1);
|
ba.assertProblem("a =", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6843,7 +6853,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// f(s);
|
// f(s);
|
||||||
// }
|
// }
|
||||||
public void testPointerToNonPointerConversion_263159() throws Exception {
|
public void testPointerToNonPointerConversion_263159() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertProblem("f(p)", 1);
|
ba.assertProblem("f(p)", 1);
|
||||||
ba.assertProblem("f(q)", 1);
|
ba.assertProblem("f(q)", 1);
|
||||||
ba.assertProblem("f(r)", 1);
|
ba.assertProblem("f(r)", 1);
|
||||||
|
@ -6860,7 +6870,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// fia(0);
|
// fia(0);
|
||||||
// }
|
// }
|
||||||
public void testNonPointerToPointerConversion_263707() throws Exception {
|
public void testNonPointerToPointerConversion_263707() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertProblem("fip(1)", 3);
|
ba.assertProblem("fip(1)", 3);
|
||||||
ba.assertProblem("fia(1)", 3);
|
ba.assertProblem("fia(1)", 3);
|
||||||
ba.assertNonProblem("fip(0)", 3, ICPPFunction.class);
|
ba.assertNonProblem("fip(0)", 3, ICPPFunction.class);
|
||||||
|
@ -6982,7 +6992,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// f(!p);
|
// f(!p);
|
||||||
// }
|
// }
|
||||||
public void testTypeOfNotExpression_265779() throws Exception {
|
public void testTypeOfNotExpression_265779() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("f(!p)", 1);
|
ba.assertNonProblem("f(!p)", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7105,7 +7115,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// (x + 1.0).b; //3
|
// (x + 1.0).b; //3
|
||||||
// }
|
// }
|
||||||
public void testOverloadResolutionForOperators_Bug266211() throws Exception {
|
public void testOverloadResolutionForOperators_Bug266211() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("a; //1", 1, ICPPField.class);
|
ba.assertNonProblem("a; //1", 1, ICPPField.class);
|
||||||
ba.assertNonProblem("a; //2", 1, ICPPField.class);
|
ba.assertNonProblem("a; //2", 1, ICPPField.class);
|
||||||
ba.assertNonProblem("b; //3", 1, ICPPField.class);
|
ba.assertNonProblem("b; //3", 1, ICPPField.class);
|
||||||
|
@ -7126,7 +7136,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// (x + 1.0).a; //2
|
// (x + 1.0).a; //2
|
||||||
// }
|
// }
|
||||||
public void testOverloadResolutionForOperators_Bug268534() throws Exception {
|
public void testOverloadResolutionForOperators_Bug268534() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("a; //1", 1, ICPPField.class);
|
ba.assertNonProblem("a; //1", 1, ICPPField.class);
|
||||||
ba.assertNonProblem("a; //2", 1, ICPPField.class);
|
ba.assertNonProblem("a; //2", 1, ICPPField.class);
|
||||||
}
|
}
|
||||||
|
@ -7140,7 +7150,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// test(c);
|
// test(c);
|
||||||
// }
|
// }
|
||||||
public void testInvalidUserDefinedConversion_Bug269729() throws Exception {
|
public void testInvalidUserDefinedConversion_Bug269729() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertProblem("test(c)", 4);
|
ba.assertProblem("test(c)", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7174,14 +7184,14 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// struct A;
|
// struct A;
|
||||||
// A a;
|
// A a;
|
||||||
public void testForwardDeclarationAfterUsing_271236() throws Exception {
|
public void testForwardDeclarationAfterUsing_271236() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertNonProblem("A a;", 1, ICPPClassType.class);
|
ba.assertNonProblem("A a;", 1, ICPPClassType.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// template <class T> class Moo;
|
// template <class T> class Moo;
|
||||||
// bool getFile(Moo <class Foo> & res);
|
// bool getFile(Moo <class Foo> & res);
|
||||||
public void testScopeOfClassFwdDecl_270831() throws Exception {
|
public void testScopeOfClassFwdDecl_270831() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ICPPClassType t= ba.assertNonProblem("Foo", 3, ICPPClassType.class);
|
ICPPClassType t= ba.assertNonProblem("Foo", 3, ICPPClassType.class);
|
||||||
IScope scope= t.getScope();
|
IScope scope= t.getScope();
|
||||||
assertEquals(EScopeKind.eGlobal, scope.getKind());
|
assertEquals(EScopeKind.eGlobal, scope.getKind());
|
||||||
|
@ -7349,7 +7359,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// f(l1);
|
// f(l1);
|
||||||
// }
|
// }
|
||||||
public void testEnumToIntConversion_285368() throws Exception {
|
public void testEnumToIntConversion_285368() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ICPPFunction f1 = ba.assertNonProblem("f(i1)", 1, ICPPFunction.class);
|
ICPPFunction f1 = ba.assertNonProblem("f(i1)", 1, ICPPFunction.class);
|
||||||
IType t1 = f1.getType().getParameterTypes()[0];
|
IType t1 = f1.getType().getParameterTypes()[0];
|
||||||
assertTrue(t1 instanceof ICPPBasicType);
|
assertTrue(t1 instanceof ICPPBasicType);
|
||||||
|
@ -7369,7 +7379,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
|
|
||||||
// typedef enum enum_name enum_name;
|
// typedef enum enum_name enum_name;
|
||||||
public void testTypedefRecursion_285457() throws Exception {
|
public void testTypedefRecursion_285457() throws Exception {
|
||||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper ba= getAssertionHelper();
|
||||||
ba.assertProblem("enum_name", 9);
|
ba.assertProblem("enum_name", 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8650,7 +8660,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// Y* m(Y*);//3
|
// Y* m(Y*);//3
|
||||||
// };
|
// };
|
||||||
public void testOverrideSimpleCovariance_Bug321617() throws Exception {
|
public void testOverrideSimpleCovariance_Bug321617() throws Exception {
|
||||||
BindingAssertionHelper helper= new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper helper= getAssertionHelper();
|
||||||
ICPPMethod m0= helper.assertNonProblem("m();//0", 1, ICPPMethod.class);
|
ICPPMethod m0= helper.assertNonProblem("m();//0", 1, ICPPMethod.class);
|
||||||
ICPPMethod m1= helper.assertNonProblem("m(X*);//1", 1, ICPPMethod.class);
|
ICPPMethod m1= helper.assertNonProblem("m(X*);//1", 1, ICPPMethod.class);
|
||||||
ICPPMethod m2= helper.assertNonProblem("m();//2", 1, ICPPMethod.class);
|
ICPPMethod m2= helper.assertNonProblem("m();//2", 1, ICPPMethod.class);
|
||||||
|
@ -9071,7 +9081,41 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// }
|
// }
|
||||||
// int j = A::i;
|
// int j = A::i;
|
||||||
public void testInlineNamespaceLookup_324096() throws Exception {
|
public void testInlineNamespaceLookup_324096() throws Exception {
|
||||||
String code= getAboveComment();
|
parseAndCheckBindings();
|
||||||
parseAndCheckBindings(code);
|
}
|
||||||
|
|
||||||
|
// struct C {
|
||||||
|
// operator int();
|
||||||
|
// };
|
||||||
|
// void f(C);
|
||||||
|
// void f(int);
|
||||||
|
// void test() {
|
||||||
|
// C c;
|
||||||
|
// f(true ? c : 1); // calls f(int), not f(C);
|
||||||
|
// }
|
||||||
|
public void testConditionalOperator_324853a() throws Exception {
|
||||||
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
|
IBinding f = bh.assertNonProblem("f(int);", 1);
|
||||||
|
IBinding ref= bh.assertNonProblem("f(true ? c : 1)", 1);
|
||||||
|
assertSame(f, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void f(char*);
|
||||||
|
// void f(const char*);
|
||||||
|
// void g(char*);
|
||||||
|
// void test(char* p, const char* cp) {
|
||||||
|
// f(0 ? cp : p);
|
||||||
|
// f(0 ? p : ""); // uses f(const char*);
|
||||||
|
// g(0 ? p : ""); // converts "" to char*
|
||||||
|
// }
|
||||||
|
public void testConditionalOperator_324853b() throws Exception {
|
||||||
|
BindingAssertionHelper bh= getAssertionHelper();
|
||||||
|
IBinding fc = bh.assertNonProblem("f(const char*);", 1);
|
||||||
|
IBinding ref;
|
||||||
|
ref= bh.assertNonProblem("f(0 ? cp : p)", 1);
|
||||||
|
assertSame(fc, ref);
|
||||||
|
ref= bh.assertNonProblem("f(0 ? p : \"\")", 1); // "" converted to char*
|
||||||
|
assertSame(fc, ref);
|
||||||
|
bh.assertNonProblem("g(0 ? p : \"\")", 1); //
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,22 +13,43 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
|
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
|
||||||
|
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.XVALUE;
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
|
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.ProblemBinding;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.Context;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
||||||
|
|
||||||
public class CPPASTConditionalExpression extends ASTNode implements IASTConditionalExpression,
|
public class CPPASTConditionalExpression extends ASTNode implements IASTConditionalExpression,
|
||||||
IASTAmbiguityParent {
|
IASTAmbiguityParent {
|
||||||
|
|
||||||
private IASTExpression condition;
|
private IASTExpression fCondition;
|
||||||
private IASTExpression negative;
|
private IASTExpression fPositive;
|
||||||
private IASTExpression positive;
|
private IASTExpression fNegative;
|
||||||
|
private IType fType;
|
||||||
|
private ValueCategory fValueCategory;
|
||||||
|
|
||||||
|
|
||||||
public CPPASTConditionalExpression() {
|
public CPPASTConditionalExpression() {
|
||||||
|
@ -43,20 +64,20 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
||||||
|
|
||||||
public CPPASTConditionalExpression copy() {
|
public CPPASTConditionalExpression copy() {
|
||||||
CPPASTConditionalExpression copy = new CPPASTConditionalExpression();
|
CPPASTConditionalExpression copy = new CPPASTConditionalExpression();
|
||||||
copy.setLogicalConditionExpression(condition == null ? null : condition.copy());
|
copy.setLogicalConditionExpression(fCondition == null ? null : fCondition.copy());
|
||||||
copy.setPositiveResultExpression(positive == null ? null : positive.copy());
|
copy.setPositiveResultExpression(fPositive == null ? null : fPositive.copy());
|
||||||
copy.setNegativeResultExpression(negative == null ? null : negative.copy());
|
copy.setNegativeResultExpression(fNegative == null ? null : fNegative.copy());
|
||||||
copy.setOffsetAndLength(this);
|
copy.setOffsetAndLength(this);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTExpression getLogicalConditionExpression() {
|
public IASTExpression getLogicalConditionExpression() {
|
||||||
return condition;
|
return fCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLogicalConditionExpression(IASTExpression expression) {
|
public void setLogicalConditionExpression(IASTExpression expression) {
|
||||||
assertNotFrozen();
|
assertNotFrozen();
|
||||||
condition = expression;
|
fCondition = expression;
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
expression.setParent(this);
|
expression.setParent(this);
|
||||||
expression.setPropertyInParent(LOGICAL_CONDITION);
|
expression.setPropertyInParent(LOGICAL_CONDITION);
|
||||||
|
@ -64,12 +85,12 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTExpression getPositiveResultExpression() {
|
public IASTExpression getPositiveResultExpression() {
|
||||||
return positive;
|
return fPositive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPositiveResultExpression(IASTExpression expression) {
|
public void setPositiveResultExpression(IASTExpression expression) {
|
||||||
assertNotFrozen();
|
assertNotFrozen();
|
||||||
this.positive = expression;
|
this.fPositive = expression;
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
expression.setParent(this);
|
expression.setParent(this);
|
||||||
expression.setPropertyInParent(POSITIVE_RESULT);
|
expression.setPropertyInParent(POSITIVE_RESULT);
|
||||||
|
@ -77,12 +98,12 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTExpression getNegativeResultExpression() {
|
public IASTExpression getNegativeResultExpression() {
|
||||||
return negative;
|
return fNegative;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNegativeResultExpression(IASTExpression expression) {
|
public void setNegativeResultExpression(IASTExpression expression) {
|
||||||
assertNotFrozen();
|
assertNotFrozen();
|
||||||
this.negative = expression;
|
this.fNegative = expression;
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
expression.setParent(this);
|
expression.setParent(this);
|
||||||
expression.setPropertyInParent(NEGATIVE_RESULT);
|
expression.setPropertyInParent(NEGATIVE_RESULT);
|
||||||
|
@ -99,60 +120,230 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( condition != null ) if( !condition.accept( action ) ) return false;
|
if (fCondition != null && !fCondition.accept(action))
|
||||||
if( positive != null ) if( !positive.accept( action ) ) return false;
|
return false;
|
||||||
if( negative != null ) if( !negative.accept( action ) ) return false;
|
if (fPositive != null && !fPositive.accept(action))
|
||||||
|
return false;
|
||||||
|
if (fNegative != null && !fNegative.accept(action))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (action.shouldVisitExpressions && action.leave(this) == ASTVisitor.PROCESS_ABORT)
|
||||||
|
return false;
|
||||||
|
|
||||||
if( action.shouldVisitExpressions ){
|
|
||||||
switch( action.leave( this ) ){
|
|
||||||
case ASTVisitor.PROCESS_ABORT : return false;
|
|
||||||
case ASTVisitor.PROCESS_SKIP : return true;
|
|
||||||
default : break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replace(IASTNode child, IASTNode other) {
|
public void replace(IASTNode child, IASTNode other) {
|
||||||
if( child == condition )
|
if (child == fCondition) {
|
||||||
{
|
|
||||||
other.setPropertyInParent(child.getPropertyInParent());
|
other.setPropertyInParent(child.getPropertyInParent());
|
||||||
other.setParent(child.getParent());
|
other.setParent(child.getParent());
|
||||||
condition = (IASTExpression) other;
|
fCondition = (IASTExpression) other;
|
||||||
}
|
}
|
||||||
if( child == positive )
|
if (child == fPositive) {
|
||||||
{
|
|
||||||
other.setPropertyInParent(child.getPropertyInParent());
|
other.setPropertyInParent(child.getPropertyInParent());
|
||||||
other.setParent(child.getParent());
|
other.setParent(child.getParent());
|
||||||
positive = (IASTExpression) other;
|
fPositive = (IASTExpression) other;
|
||||||
}
|
}
|
||||||
if( child == negative )
|
if (child == fNegative) {
|
||||||
{
|
|
||||||
other.setPropertyInParent(child.getPropertyInParent());
|
other.setPropertyInParent(child.getPropertyInParent());
|
||||||
other.setParent(child.getParent());
|
other.setParent(child.getParent());
|
||||||
negative = (IASTExpression) other;
|
fNegative = (IASTExpression) other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mstodo conditional operator (type)
|
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
IASTExpression positiveExpression = getPositiveResultExpression();
|
evaluate();
|
||||||
if (positiveExpression == null) {
|
return fType;
|
||||||
positiveExpression= getLogicalConditionExpression();
|
|
||||||
}
|
|
||||||
IType t2 = positiveExpression.getExpressionType();
|
|
||||||
IType t3 = getNegativeResultExpression().getExpressionType();
|
|
||||||
if (t3 instanceof IPointerType || t2 == null)
|
|
||||||
return t3;
|
|
||||||
return t2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// mstodo conditional operator (value category)
|
|
||||||
public ValueCategory getValueCategory() {
|
public ValueCategory getValueCategory() {
|
||||||
return PRVALUE;
|
evaluate();
|
||||||
|
return fValueCategory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLValue() {
|
public boolean isLValue() {
|
||||||
return getValueCategory() == LVALUE;
|
return getValueCategory() == LVALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void evaluate() {
|
||||||
|
if (fValueCategory != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fValueCategory= PRVALUE;
|
||||||
|
|
||||||
|
// Gnu-extension: Empty positive expression is replaced by condition.
|
||||||
|
IASTExpression expr2 = getPositiveResultExpression();
|
||||||
|
final IASTExpression expr3 = getNegativeResultExpression();
|
||||||
|
if (expr2 == null) {
|
||||||
|
expr2= getLogicalConditionExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
IType t2 = expr2.getExpressionType();
|
||||||
|
IType t3 = expr3.getExpressionType();
|
||||||
|
if (t2 == null || t3 == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
final IType uqt2= getNestedType(t2, TDEF | REF | CVTYPE);
|
||||||
|
final IType uqt3= getNestedType(t3, TDEF | REF | CVTYPE);
|
||||||
|
if (uqt2 instanceof IProblemBinding || uqt2 instanceof ICPPUnknownType) {
|
||||||
|
fType= uqt2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (uqt3 instanceof IProblemBinding || uqt3 instanceof ICPPUnknownType) {
|
||||||
|
fType= uqt3;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean void2= isVoidType(uqt2);
|
||||||
|
final boolean void3= isVoidType(uqt3);
|
||||||
|
|
||||||
|
// Void types: Either both are void or one is a throw expression.
|
||||||
|
if (void2 || void3) {
|
||||||
|
if (isThrowExpression(expr2)) {
|
||||||
|
fType= Conversions.lvalue_to_rvalue(t3);
|
||||||
|
} else if (isThrowExpression(expr3)) {
|
||||||
|
fType= Conversions.lvalue_to_rvalue(t2);
|
||||||
|
} else if (void2 && void3) {
|
||||||
|
fType= uqt2;
|
||||||
|
} else {
|
||||||
|
createProblem();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ValueCategory vcat2= expr2.getValueCategory();
|
||||||
|
final ValueCategory vcat3= expr3.getValueCategory();
|
||||||
|
final boolean isClassType2 = uqt2 instanceof ICPPClassType;
|
||||||
|
final boolean isClassType3 = uqt3 instanceof ICPPClassType;
|
||||||
|
|
||||||
|
// Same type and same value category
|
||||||
|
if (t2.isSameType(t3)) {
|
||||||
|
if (vcat2 == vcat3) {
|
||||||
|
fType= t2;
|
||||||
|
fValueCategory= vcat2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Different types with at least one class type
|
||||||
|
if (isClassType2 || isClassType3) {
|
||||||
|
final Cost cost2= convertToMatch(t2, vcat2, uqt2, t3, vcat3, uqt3); // sets fType and fValueCategory
|
||||||
|
final Cost cost3= convertToMatch(t3, vcat3, uqt3, t2, vcat2, uqt2); // sets fType and fValueCategory
|
||||||
|
if (cost2.converts() || cost3.converts()) {
|
||||||
|
if (cost2.converts()) {
|
||||||
|
if (cost3.converts() || cost2.isAmbiguousUDC()) {
|
||||||
|
fType= createProblem();
|
||||||
|
}
|
||||||
|
} else if (cost3.isAmbiguousUDC()) {
|
||||||
|
fType= createProblem();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (vcat2 == vcat3 && vcat2.isGLValue() && uqt2.isSameType(uqt3)) {
|
||||||
|
// Two lvalues or two xvalues with same type up to qualification.
|
||||||
|
final CVQualifier cv2 = SemanticUtil.getCVQualifier(t2);
|
||||||
|
final CVQualifier cv3 = SemanticUtil.getCVQualifier(t3);
|
||||||
|
if (cv2.isAtLeastAsQualifiedAs(cv3)) {
|
||||||
|
fType= t2;
|
||||||
|
fValueCategory= vcat2;
|
||||||
|
} else if (cv3.isAtLeastAsQualifiedAs(cv2)) {
|
||||||
|
fType= t3;
|
||||||
|
fValueCategory= vcat3;
|
||||||
|
} else {
|
||||||
|
createProblem();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5.16-5: At least one class type but no conversion
|
||||||
|
if (isClassType2 || isClassType3) {
|
||||||
|
ICPPFunction builtin = CPPSemantics.findOverloadedConditionalOperator(expr2, expr3);
|
||||||
|
if (builtin != null) {
|
||||||
|
fType= ExpressionTypes.typeFromFunctionCall(builtin);
|
||||||
|
}
|
||||||
|
createProblem();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5.16-6
|
||||||
|
t2= Conversions.lvalue_to_rvalue(t2);
|
||||||
|
t3= Conversions.lvalue_to_rvalue(t3);
|
||||||
|
if (t2.isSameType(t3)) {
|
||||||
|
fType= t2;
|
||||||
|
} else {
|
||||||
|
fType= CPPArithmeticConversion.convertCppOperandTypes(IASTBinaryExpression.op_plus, t2, t3);
|
||||||
|
if (fType == null) {
|
||||||
|
fType= Conversions.compositePointerType(t2, t3);
|
||||||
|
if (fType == null) {
|
||||||
|
createProblem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isThrowExpression(IASTExpression expr) {
|
||||||
|
while (expr instanceof IASTUnaryExpression) {
|
||||||
|
final IASTUnaryExpression unaryExpr = (IASTUnaryExpression) expr;
|
||||||
|
final int op = unaryExpr.getOperator();
|
||||||
|
if (op == IASTUnaryExpression.op_throw) {
|
||||||
|
return true;
|
||||||
|
} else if (op == IASTUnaryExpression.op_bracketedPrimary) {
|
||||||
|
expr= unaryExpr.getOperand();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cost convertToMatch(IType t1, ValueCategory vcat1, IType uqt1, IType t2, ValueCategory vcat2, IType uqt2) {
|
||||||
|
// E2 is an lvalue or E2 is an xvalue
|
||||||
|
try {
|
||||||
|
if (vcat2.isGLValue()) {
|
||||||
|
IType target= new CPPReferenceType(t2, vcat2 == XVALUE);
|
||||||
|
Cost c= Conversions.checkImplicitConversionSequence(target, t1, vcat1, UDCMode.ALLOWED, Context.REQUIRE_DIRECT_BINDING);
|
||||||
|
if (c.converts()) {
|
||||||
|
fType= t2;
|
||||||
|
fValueCategory= vcat2;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Both are class types and one derives from the other
|
||||||
|
if (uqt1 instanceof ICPPClassType && uqt2 instanceof ICPPClassType) {
|
||||||
|
int dist= SemanticUtil.calculateInheritanceDepth(uqt1, uqt2);
|
||||||
|
if (dist >= 0) {
|
||||||
|
CVQualifier cv1 = SemanticUtil.getCVQualifier(t1);
|
||||||
|
CVQualifier cv2 = SemanticUtil.getCVQualifier(t2);
|
||||||
|
if (cv2.isAtLeastAsQualifiedAs(cv1)) {
|
||||||
|
fType= t2;
|
||||||
|
fValueCategory= PRVALUE;
|
||||||
|
return new Cost(t1, t2, Rank.IDENTITY);
|
||||||
|
}
|
||||||
|
return Cost.NO_CONVERSION;
|
||||||
|
}
|
||||||
|
if (SemanticUtil.calculateInheritanceDepth(uqt2, uqt1) >= 0)
|
||||||
|
return Cost.NO_CONVERSION;
|
||||||
|
}
|
||||||
|
// Unrelated class types or just one class:
|
||||||
|
if (vcat2 != PRVALUE) {
|
||||||
|
t2= Conversions.lvalue_to_rvalue(t2);
|
||||||
|
}
|
||||||
|
Cost c= Conversions.checkImplicitConversionSequence(t2, t1, vcat1, UDCMode.ALLOWED, Context.ORDINARY);
|
||||||
|
if (c.converts()) {
|
||||||
|
fType= t2;
|
||||||
|
fValueCategory= PRVALUE;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
} catch (DOMException e) {
|
||||||
|
}
|
||||||
|
return Cost.NO_CONVERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProblemBinding createProblem() {
|
||||||
|
return new ProblemBinding(this, IProblemBinding.SEMANTIC_INVALID_TYPE, this.getRawSignature().toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVoidType(IType t) {
|
||||||
|
return t instanceof ICPPBasicType && ((ICPPBasicType) t).getKind() == Kind.eVoid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2588,7 +2588,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
simpleType= IASTSimpleDeclSpecifier.t_decltype;
|
simpleType= IASTSimpleDeclSpecifier.t_decltype;
|
||||||
consume(IToken.t_decltype);
|
consume(IToken.t_decltype);
|
||||||
consume(IToken.tLPAREN);
|
consume(IToken.tLPAREN);
|
||||||
typeofExpression= unaryExpression(CastExprCtx.eNotBExpr);
|
typeofExpression= expression();
|
||||||
endOffset= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
endOffset= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
||||||
|
|
||||||
encounteredTypename= true;
|
encounteredTypename= true;
|
||||||
|
|
|
@ -70,7 +70,12 @@ public enum OverloadableOperator {
|
||||||
NEW("new"),
|
NEW("new"),
|
||||||
DELETE_ARRAY("delete[]"),
|
DELETE_ARRAY("delete[]"),
|
||||||
DELETE("delete"),
|
DELETE("delete"),
|
||||||
NEW_ARRAY("new[]");
|
NEW_ARRAY("new[]"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cannot be overloaded by the user, however overload resolution needs to be performed.
|
||||||
|
*/
|
||||||
|
CONDITIONAL_OPERATOR("?");
|
||||||
|
|
||||||
private final char[] rep;
|
private final char[] rep;
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
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;
|
||||||
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.ICPPEnumeration;
|
||||||
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.ICPPFunctionType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
|
@ -217,6 +218,11 @@ class BuiltinOperators {
|
||||||
case NOT:
|
case NOT:
|
||||||
addFunction(BOOL, BOOL);
|
addFunction(BOOL, BOOL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CONDITIONAL_OPERATOR:
|
||||||
|
binaryPromotedArithmetic(true, ReturnType.CONVERT);
|
||||||
|
conditional();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fResult == null)
|
if (fResult == null)
|
||||||
|
@ -516,6 +522,19 @@ class BuiltinOperators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 13.6-25
|
||||||
|
private void conditional() {
|
||||||
|
for (int i = FIRST; i <= SECOND; i++) {
|
||||||
|
IType[] types= getClassConversionTypes(i);
|
||||||
|
for (IType type : types) {
|
||||||
|
type= SemanticUtil.getNestedType(type, TDEF|REF|CVTYPE);
|
||||||
|
if (isPointer(type) || isScopedEnumeration(type) || isPointerToMember(type)) {
|
||||||
|
addFunction(type, type, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void addFunction(IType returnType, IType p1) {
|
private void addFunction(IType returnType, IType p1) {
|
||||||
addFunction(returnType, new IType[] {p1});
|
addFunction(returnType, new IType[] {p1});
|
||||||
}
|
}
|
||||||
|
@ -557,6 +576,10 @@ class BuiltinOperators {
|
||||||
return type instanceof IEnumeration;
|
return type instanceof IEnumeration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isScopedEnumeration(IType type) {
|
||||||
|
return type instanceof ICPPEnumeration && ((ICPPEnumeration) type).isScoped();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isPointer(IType type) {
|
private boolean isPointer(IType type) {
|
||||||
return type instanceof IPointerType && !(type instanceof ICPPPointerToMemberType);
|
return type instanceof IPointerType && !(type instanceof ICPPPointerToMemberType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2825,7 +2825,7 @@ public class CPPSemantics {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
IASTExpression arg = createArgForType(fieldReference, type);
|
IASTExpression arg = createArgForType(fieldReference, type);
|
||||||
ICPPFunction op = findOverloadedOperator(fieldReference, new IASTExpression[] {arg}, uTemp, OverloadableOperator.ARROW, NonMemberMode.none);
|
ICPPFunction op = findOverloadedOperator(fieldReference, new IASTExpression[] {arg}, uTemp, OverloadableOperator.ARROW, LookupMode.NO_GLOBALS);
|
||||||
if (op == null)
|
if (op == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2852,7 +2852,7 @@ public class CPPSemantics {
|
||||||
IASTInitializerClause[] args = {exp.getArrayExpression(), exp.getArgument()};
|
IASTInitializerClause[] args = {exp.getArrayExpression(), exp.getArgument()};
|
||||||
IType type = exp.getArrayExpression().getExpressionType();
|
IType type = exp.getArrayExpression().getExpressionType();
|
||||||
type = SemanticUtil.getUltimateTypeUptoPointers(type);
|
type = SemanticUtil.getUltimateTypeUptoPointers(type);
|
||||||
return findOverloadedOperator(exp, args, type, OverloadableOperator.BRACKET, NonMemberMode.none);
|
return findOverloadedOperator(exp, args, type, OverloadableOperator.BRACKET, LookupMode.NO_GLOBALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(IASTFunctionCallExpression exp, ICPPClassType type) {
|
public static ICPPFunction findOverloadedOperator(IASTFunctionCallExpression exp, ICPPClassType type) {
|
||||||
|
@ -2864,7 +2864,7 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
args = argsToPass.toArray(new IASTInitializerClause[argsToPass.size()]);
|
args = argsToPass.toArray(new IASTInitializerClause[argsToPass.size()]);
|
||||||
|
|
||||||
return findOverloadedOperator(exp, args, type, OverloadableOperator.PAREN, NonMemberMode.none);
|
return findOverloadedOperator(exp, args, type, OverloadableOperator.PAREN, LookupMode.NO_GLOBALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(ICPPASTNewExpression exp) {
|
public static ICPPFunction findOverloadedOperator(ICPPASTNewExpression exp) {
|
||||||
|
@ -2888,14 +2888,14 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IASTInitializerClause[] argArray = args.toArray(new IASTInitializerClause[args.size()]);
|
IASTInitializerClause[] argArray = args.toArray(new IASTInitializerClause[args.size()]);
|
||||||
return findOverloadedOperator(exp, argArray, type, op, NonMemberMode.all);
|
return findOverloadedOperator(exp, argArray, type, op, LookupMode.ALL_GLOBALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
|
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
|
||||||
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
|
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
|
||||||
IType classType = getNestedClassType(exp);
|
IType classType = getNestedClassType(exp);
|
||||||
IASTExpression[] args = new IASTExpression[] {createArgForType(exp, classType)};
|
IASTExpression[] args = new IASTExpression[] {createArgForType(exp, classType)};
|
||||||
return findOverloadedOperator(exp, args, classType, op, NonMemberMode.all);
|
return findOverloadedOperator(exp, args, classType, op, LookupMode.ALL_GLOBALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ICPPClassType getNestedClassType(ICPPASTDeleteExpression exp) {
|
private static ICPPClassType getNestedClassType(ICPPASTDeleteExpression exp) {
|
||||||
|
@ -3063,7 +3063,7 @@ public class CPPSemantics {
|
||||||
if (!isUserDefined(type))
|
if (!isUserDefined(type))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return findOverloadedOperator(exp, args, type, op, NonMemberMode.limited);
|
return findOverloadedOperator(exp, args, type, op, LookupMode.LIMITED_GLOBALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) {
|
public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) {
|
||||||
|
@ -3081,13 +3081,24 @@ public class CPPSemantics {
|
||||||
if (!isUserDefined(op1type) && !isUserDefined(op2type))
|
if (!isUserDefined(op1type) && !isUserDefined(op2type))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
IASTExpression[] args = new IASTExpression[] { op1, op2 };
|
final IASTExpression[] args = new IASTExpression[] { op1, op2 };
|
||||||
NonMemberMode lookupNonMember = NonMemberMode.none;
|
final LookupMode lookupNonMember;
|
||||||
if (exp.getOperator() != IASTBinaryExpression.op_assign) {
|
if (exp.getOperator() == IASTBinaryExpression.op_assign) {
|
||||||
lookupNonMember= NonMemberMode.limited;
|
lookupNonMember = LookupMode.NO_GLOBALS;
|
||||||
|
} else {
|
||||||
|
lookupNonMember= LookupMode.LIMITED_GLOBALS;
|
||||||
|
}
|
||||||
|
return findOverloadedOperator(exp, args, op1type, op, lookupNonMember);
|
||||||
}
|
}
|
||||||
|
|
||||||
return findOverloadedOperator(exp, args, op1type, op, lookupNonMember);
|
/**
|
||||||
|
* For simplicity returns an operator of form RT (T, T) rather than RT (boolean, T, T)
|
||||||
|
*/
|
||||||
|
public static ICPPFunction findOverloadedConditionalOperator(IASTExpression positive, IASTExpression negative) {
|
||||||
|
final IASTExpression parent = (IASTExpression) positive.getParent();
|
||||||
|
final IASTExpression[] args = new IASTExpression[] {positive, negative};
|
||||||
|
return findOverloadedOperator(parent, args, null,
|
||||||
|
OverloadableOperator.CONDITIONAL_OPERATOR, LookupMode.NO_GLOBALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3106,12 +3117,12 @@ public class CPPSemantics {
|
||||||
dummy.setParent(first);
|
dummy.setParent(first);
|
||||||
|
|
||||||
IASTExpression[] args = new IASTExpression[] { dummy , second };
|
IASTExpression[] args = new IASTExpression[] { dummy , second };
|
||||||
return findOverloadedOperator(dummy, args, lookupType, OverloadableOperator.COMMA, NonMemberMode.limited);
|
return findOverloadedOperator(dummy, args, lookupType, OverloadableOperator.COMMA, LookupMode.LIMITED_GLOBALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static enum NonMemberMode {none, limited, all}
|
private static enum LookupMode {NO_GLOBALS, LIMITED_GLOBALS, ALL_GLOBALS}
|
||||||
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTInitializerClause[] args, IType methodLookupType,
|
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTInitializerClause[] args, IType methodLookupType,
|
||||||
OverloadableOperator operator, NonMemberMode mode) {
|
OverloadableOperator operator, LookupMode mode) {
|
||||||
ICPPClassType callToObjectOfClassType= null;
|
ICPPClassType callToObjectOfClassType= null;
|
||||||
IType type2= null;
|
IType type2= null;
|
||||||
if (args.length >= 2 && args[1] instanceof IASTExpression) {
|
if (args.length >= 2 && args[1] instanceof IASTExpression) {
|
||||||
|
@ -3158,9 +3169,9 @@ public class CPPSemantics {
|
||||||
LookupData funcData = new LookupData(funcName);
|
LookupData funcData = new LookupData(funcName);
|
||||||
funcData.setFunctionArguments(true, args);
|
funcData.setFunctionArguments(true, args);
|
||||||
funcData.ignoreMembers = true; // (13.3.1.2.3)
|
funcData.ignoreMembers = true; // (13.3.1.2.3)
|
||||||
if (mode != NonMemberMode.none || callToObjectOfClassType != null) {
|
if (mode != LookupMode.NO_GLOBALS || callToObjectOfClassType != null) {
|
||||||
try {
|
try {
|
||||||
if (mode != NonMemberMode.none) {
|
if (mode != LookupMode.NO_GLOBALS) {
|
||||||
IScope scope = CPPVisitor.getContainingScope(parent);
|
IScope scope = CPPVisitor.getContainingScope(parent);
|
||||||
if (scope == null)
|
if (scope == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -3195,7 +3206,7 @@ public class CPPSemantics {
|
||||||
|
|
||||||
// 13.3.1.2.3
|
// 13.3.1.2.3
|
||||||
// However, if no operand type has class type, only those non-member functions ...
|
// However, if no operand type has class type, only those non-member functions ...
|
||||||
if (mode == NonMemberMode.limited) {
|
if (mode == LookupMode.LIMITED_GLOBALS) {
|
||||||
if (funcData.foundItems != null && !(methodLookupType instanceof ICPPClassType) && !(type2 instanceof ICPPClassType)) {
|
if (funcData.foundItems != null && !(methodLookupType instanceof ICPPClassType) && !(type2 instanceof ICPPClassType)) {
|
||||||
IEnumeration enum1= null;
|
IEnumeration enum1= null;
|
||||||
IEnumeration enum2= null;
|
IEnumeration enum2= null;
|
||||||
|
|
|
@ -50,11 +50,13 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
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.ITypeContainer;
|
||||||
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.CPPASTName;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||||
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.CPPQualifierType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
||||||
|
@ -64,8 +66,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.ReferenceBind
|
||||||
* Routines for calculating the cost of conversions.
|
* Routines for calculating the cost of conversions.
|
||||||
*/
|
*/
|
||||||
public class Conversions {
|
public class Conversions {
|
||||||
enum UDCMode {ALLOWED, FORBIDDEN, DEFER}
|
public enum UDCMode {ALLOWED, FORBIDDEN, DEFER}
|
||||||
enum Context {ORDINARY, IMPLICIT_OBJECT, FIRST_PARAM_OF_DIRECT_COPY_CTOR}
|
public enum Context {ORDINARY, IMPLICIT_OBJECT, FIRST_PARAM_OF_DIRECT_COPY_CTOR, REQUIRE_DIRECT_BINDING}
|
||||||
|
|
||||||
private static final char[] INITIALIZER_LIST_NAME = "initializer_list".toCharArray(); //$NON-NLS-1$
|
private static final char[] INITIALIZER_LIST_NAME = "initializer_list".toCharArray(); //$NON-NLS-1$
|
||||||
private static final char[] STD_NAME = "std".toCharArray(); //$NON-NLS-1$
|
private static final char[] STD_NAME = "std".toCharArray(); //$NON-NLS-1$
|
||||||
|
@ -221,7 +223,7 @@ public class Conversions {
|
||||||
// as, or greater cv-qualification than, cv2; otherwise, the program is ill-formed.
|
// 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
|
// 13.3.3.1.7 no temporary object when converting the implicit object parameter
|
||||||
if (!isImpliedObject) {
|
if (!isImpliedObject && ctx != Context.REQUIRE_DIRECT_BINDING) {
|
||||||
if (isReferenceRelated(T1, T2) < 0 || compareQualifications(cv1T1, cv2T2) >= 0) {
|
if (isReferenceRelated(T1, T2) < 0 || compareQualifications(cv1T1, cv2T2) >= 0) {
|
||||||
Cost cost= nonReferenceConversion(valueCat, cv2T2, T1, udc, false);
|
Cost cost= nonReferenceConversion(valueCat, cv2T2, T1, udc, false);
|
||||||
if (!isImplicitWithoutRefQualifier && cost.converts()) {
|
if (!isImplicitWithoutRefQualifier && cost.converts()) {
|
||||||
|
@ -808,38 +810,25 @@ public class Conversions {
|
||||||
|
|
||||||
// 4.2 array to pointer conversion
|
// 4.2 array to pointer conversion
|
||||||
if (source instanceof IArrayType) {
|
if (source instanceof IArrayType) {
|
||||||
final IArrayType arrayType= (IArrayType) source;
|
|
||||||
|
|
||||||
boolean isConverted= false;
|
|
||||||
if (target instanceof IPointerType) {
|
if (target instanceof IPointerType) {
|
||||||
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
|
|
||||||
|
|
||||||
// 4.2-2 a string literal can be converted to pointer to char
|
// 4.2-2 a string literal can be converted to pointer to char
|
||||||
if (!(targetPtrTgt instanceof IQualifierType) || !((IQualifierType) targetPtrTgt).isConst()) {
|
source = unqualifyStringLiteral(source, (IPointerType) target, cost);
|
||||||
IType tmp= arrayType.getType();
|
|
||||||
if (tmp instanceof IQualifierType && ((IQualifierType) tmp).isConst()) {
|
|
||||||
tmp= ((IQualifierType) tmp).getType();
|
|
||||||
if (tmp instanceof CPPBasicType) {
|
|
||||||
IASTExpression val = ((CPPBasicType) tmp).getCreatedFromExpression();
|
|
||||||
if (val instanceof IASTLiteralExpression) {
|
|
||||||
IASTLiteralExpression lit= (IASTLiteralExpression) val;
|
|
||||||
if (lit.getKind() == IASTLiteralExpression.lk_string_literal) {
|
|
||||||
source= new CPPPointerType(tmp, false, false);
|
|
||||||
cost.setQualificationAdjustment(getCVQualifier(targetPtrTgt).isVolatile() ? 2 : 1);
|
|
||||||
isConverted= true;
|
|
||||||
}
|
}
|
||||||
}
|
if (!(source instanceof IPointerType)) {
|
||||||
}
|
source = new CPPPointerType(getNestedType(((IArrayType) source).getType(), TDEF));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isConverted) {
|
|
||||||
source = new CPPPointerType(getNestedType(arrayType.getType(), TDEF));
|
|
||||||
}
|
}
|
||||||
} else if (source instanceof IFunctionType) {
|
} else if (source instanceof IFunctionType) {
|
||||||
// 4.3 function to pointer conversion
|
// 4.3 function to pointer conversion
|
||||||
source = new CPPPointerType(source);
|
source = new CPPPointerType(source);
|
||||||
} else {
|
} else {
|
||||||
|
if (source instanceof IPointerType) {
|
||||||
|
// A string literal may have been converted to a pointer when
|
||||||
|
// computing the type of a conditional expression.
|
||||||
|
if (target instanceof IPointerType) {
|
||||||
|
// 4.2-2 a string literal can be converted to pointer to char
|
||||||
|
source = unqualifyStringLiteral(source, (IPointerType) target, cost);
|
||||||
|
}
|
||||||
|
}
|
||||||
source = getNestedType(source, TDEF | REF | ALLCVQ);
|
source = getNestedType(source, TDEF | REF | ALLCVQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -852,6 +841,35 @@ public class Conversions {
|
||||||
return source.isSameType(target);
|
return source.isSameType(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IType unqualifyStringLiteral(IType source, final IPointerType target, final Cost cost) {
|
||||||
|
if (target instanceof ICPPPointerToMemberType)
|
||||||
|
return source;
|
||||||
|
|
||||||
|
final IType targetPtrTgt= getNestedType((target).getType(), TDEF);
|
||||||
|
if (targetPtrTgt instanceof IQualifierType && ((IQualifierType) targetPtrTgt).isConst())
|
||||||
|
return source;
|
||||||
|
|
||||||
|
IType srcTarget= ((ITypeContainer) source).getType();
|
||||||
|
if (!(srcTarget instanceof IQualifierType))
|
||||||
|
return source;
|
||||||
|
|
||||||
|
final IQualifierType srcQTarget= (IQualifierType) srcTarget;
|
||||||
|
if (srcQTarget.isConst() && !srcQTarget.isVolatile()) {
|
||||||
|
srcTarget= srcQTarget.getType();
|
||||||
|
if (srcTarget instanceof CPPBasicType) {
|
||||||
|
IASTExpression val = ((CPPBasicType) srcTarget).getCreatedFromExpression();
|
||||||
|
if (val instanceof IASTLiteralExpression) {
|
||||||
|
IASTLiteralExpression lit= (IASTLiteralExpression) val;
|
||||||
|
if (lit.getKind() == IASTLiteralExpression.lk_string_literal) {
|
||||||
|
source= new CPPPointerType(srcTarget, false, false);
|
||||||
|
cost.setQualificationAdjustment(getCVQualifier(targetPtrTgt).isVolatile() ? 2 : 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [4.4] Qualifications
|
* [4.4] Qualifications
|
||||||
* @param cost
|
* @param cost
|
||||||
|
@ -870,22 +888,12 @@ public class Conversions {
|
||||||
final int cmp= compareQualifications(t, s); // is t more qualified than s?
|
final int cmp= compareQualifications(t, s); // is t more qualified than s?
|
||||||
if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
|
if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
final boolean sIsPtrToMember = s instanceof ICPPPointerToMemberType;
|
|
||||||
final boolean tIsPtrToMember = t instanceof ICPPPointerToMemberType;
|
|
||||||
if (sIsPtrToMember != tIsPtrToMember) {
|
|
||||||
return false;
|
|
||||||
} else if (sIsPtrToMember) {
|
|
||||||
final IType sMemberOf = ((ICPPPointerToMemberType) s).getMemberOfClass();
|
|
||||||
final IType tMemberOf = ((ICPPPointerToMemberType) t).getMemberOfClass();
|
|
||||||
if (sMemberOf == null || tMemberOf == null || !sMemberOf.isSameType(tMemberOf)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final IPointerType tPtr = (IPointerType) t;
|
final IPointerType tPtr = (IPointerType) t;
|
||||||
final IPointerType sPtr = (IPointerType) s;
|
final IPointerType sPtr = (IPointerType) s;
|
||||||
|
if (haveMemberPtrConflict(sPtr, tPtr))
|
||||||
|
return false;
|
||||||
|
|
||||||
constInEveryCV2k &= (firstPointer || tPtr.isConst());
|
constInEveryCV2k &= (firstPointer || tPtr.isConst());
|
||||||
s= sPtr.getType();
|
s= sPtr.getType();
|
||||||
t= tPtr.getType();
|
t= tPtr.getType();
|
||||||
|
@ -912,6 +920,22 @@ public class Conversions {
|
||||||
return s != null && t != null && s.isSameType(t);
|
return s != null && t != null && s.isSameType(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean haveMemberPtrConflict(IPointerType s, IPointerType t) {
|
||||||
|
final boolean sIsPtrToMember = s instanceof ICPPPointerToMemberType;
|
||||||
|
final boolean tIsPtrToMember = t instanceof ICPPPointerToMemberType;
|
||||||
|
if (sIsPtrToMember != tIsPtrToMember) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (sIsPtrToMember) {
|
||||||
|
final IType sMemberOf = ((ICPPPointerToMemberType) s).getMemberOfClass();
|
||||||
|
final IType tMemberOf = ((ICPPPointerToMemberType) t).getMemberOfClass();
|
||||||
|
if (sMemberOf == null || tMemberOf == null || !sMemberOf.isSameType(tMemberOf)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts promotions and returns whether the promotion converted the type.
|
* Attempts promotions and returns whether the promotion converted the type.
|
||||||
*
|
*
|
||||||
|
@ -1041,18 +1065,14 @@ public class Conversions {
|
||||||
|
|
||||||
if (t instanceof IPointerType) {
|
if (t instanceof IPointerType) {
|
||||||
IPointerType tgtPtr= (IPointerType) t;
|
IPointerType tgtPtr= (IPointerType) t;
|
||||||
if (s instanceof CPPBasicType) {
|
|
||||||
// 4.10-1 an integral constant expression of integer type that evaluates to 0 can
|
// 4.10-1 an integral constant expression of integer type that evaluates to 0 can
|
||||||
// be converted to a pointer type
|
// be converted to a pointer type
|
||||||
// 4.11-1 same for pointer to member
|
// 4.11-1 same for pointer to member
|
||||||
IASTExpression exp = ((CPPBasicType) s).getCreatedFromExpression();
|
if (s instanceof IBasicType) {
|
||||||
if (exp != null) {
|
if (isNullPointerConstant(s)) {
|
||||||
Long val= Value.create(exp, Value.MAX_RECURSION_DEPTH).numericalValue();
|
|
||||||
if (val != null && val == 0) {
|
|
||||||
cost.setRank(Rank.CONVERSION);
|
cost.setRank(Rank.CONVERSION);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (s instanceof IPointerType) {
|
if (s instanceof IPointerType) {
|
||||||
|
@ -1119,6 +1139,19 @@ public class Conversions {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isNullPointerConstant(IType s) {
|
||||||
|
if (s instanceof CPPBasicType) {
|
||||||
|
IASTExpression exp = ((CPPBasicType) s).getCreatedFromExpression();
|
||||||
|
if (exp != null) {
|
||||||
|
Long val= Value.create(exp, Value.MAX_RECURSION_DEPTH).numericalValue();
|
||||||
|
if (val != null && val == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 4.1, 4.2, 4.3
|
* 4.1, 4.2, 4.3
|
||||||
*/
|
*/
|
||||||
|
@ -1136,4 +1169,112 @@ public class Conversions {
|
||||||
}
|
}
|
||||||
return uqType;
|
return uqType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composite pointer type computed as described in 5.9-2 except that if the conversion to the
|
||||||
|
* pointer is not possible, we return null.
|
||||||
|
*/
|
||||||
|
public static IType compositePointerType(IType t1, IType t2) {
|
||||||
|
final boolean isPtr1 = t1 instanceof IPointerType;
|
||||||
|
if (isPtr1 || isNullPtr(t1)) {
|
||||||
|
if (isNullPointerConstant(t2)) {
|
||||||
|
return t1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final boolean isPtr2 = t2 instanceof IPointerType;
|
||||||
|
if (isPtr2 || isNullPtr(t2)) {
|
||||||
|
if (isNullPointerConstant(t1)) {
|
||||||
|
return t2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isPtr1 || !isPtr2)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
final IPointerType p1= (IPointerType) t1;
|
||||||
|
final IPointerType p2= (IPointerType) t2;
|
||||||
|
if (haveMemberPtrConflict(p1, p2))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
final IType target1 = p1.getType();
|
||||||
|
if (isVoidType(target1)) {
|
||||||
|
return addQualifiers(p1, p2.isConst(), p2.isVolatile());
|
||||||
|
}
|
||||||
|
final IType target2 = p2.getType();
|
||||||
|
if (isVoidType(target2)) {
|
||||||
|
return addQualifiers(p2, p1.isConst(), p1.isVolatile());
|
||||||
|
}
|
||||||
|
|
||||||
|
IType t= mergePointers(target1, target2, true);
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
if (t == target1)
|
||||||
|
return p1;
|
||||||
|
if (t == target2)
|
||||||
|
return p2;
|
||||||
|
return copyPointer(p1, t, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IType mergePointers(IType t1, IType t2, boolean allcq) {
|
||||||
|
t1= getNestedType(t1, TDEF | REF);
|
||||||
|
t2= getNestedType(t2, TDEF | REF);
|
||||||
|
if (t1 instanceof IPointerType && t2 instanceof IPointerType) {
|
||||||
|
final IPointerType p1 = (IPointerType) t1;
|
||||||
|
final IPointerType p2 = (IPointerType) t2;
|
||||||
|
final CVQualifier cv1= getCVQualifier(t1);
|
||||||
|
final CVQualifier cv2= getCVQualifier(t2);
|
||||||
|
if (haveMemberPtrConflict(p1, p2))
|
||||||
|
return null;
|
||||||
|
if (!allcq && cv1 != cv2)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
final IType p1target = p1.getType();
|
||||||
|
IType merged= mergePointers(p1target, p2.getType(), allcq && (cv1.isConst() || cv2.isConst()));
|
||||||
|
if (merged == null)
|
||||||
|
return null;
|
||||||
|
if (p1target == merged && cv1.isAtLeastAsQualifiedAs(cv2))
|
||||||
|
return p1;
|
||||||
|
if (p2.getType() == merged && cv2.isAtLeastAsQualifiedAs(cv1))
|
||||||
|
return p2;
|
||||||
|
|
||||||
|
return copyPointer(p1, merged, cv1.isConst() || cv2.isConst(), cv1.isVolatile() || cv2.isVolatile());
|
||||||
|
}
|
||||||
|
|
||||||
|
final IType uq1= getNestedType(t1, TDEF|REF|CVTYPE);
|
||||||
|
final IType uq2= getNestedType(t2, TDEF|REF|CVTYPE);
|
||||||
|
if (uq1 == null || ! uq1.isSameType(uq2))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (uq1 == t1 && uq2 == t2)
|
||||||
|
return t1;
|
||||||
|
|
||||||
|
CVQualifier cv1= getCVQualifier(t1);
|
||||||
|
CVQualifier cv2= getCVQualifier(t2);
|
||||||
|
if (cv1 == cv2)
|
||||||
|
return t1;
|
||||||
|
|
||||||
|
if (!allcq)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (cv1.isAtLeastAsQualifiedAs(cv2))
|
||||||
|
return t1;
|
||||||
|
if (cv2.isAtLeastAsQualifiedAs(cv1))
|
||||||
|
return t2;
|
||||||
|
|
||||||
|
// One type is const the other is volatile.
|
||||||
|
return new CPPQualifierType(uq1, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IType copyPointer(final IPointerType p1, IType target, final boolean isConst,
|
||||||
|
final boolean isVolatile) {
|
||||||
|
if (p1 instanceof ICPPPointerToMemberType) {
|
||||||
|
ICPPPointerToMemberType ptm= (ICPPPointerToMemberType) p1;
|
||||||
|
return new CPPPointerToMemberType(target, ptm.getMemberOfClass(), isConst, isVolatile);
|
||||||
|
}
|
||||||
|
return new CPPPointerType(target, isConst, isVolatile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isNullPtr(IType t1) {
|
||||||
|
// mstodo null-ptr type
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,11 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||||
*
|
*
|
||||||
* See [over.best.ics] 13.3.3.1.
|
* See [over.best.ics] 13.3.3.1.
|
||||||
*/
|
*/
|
||||||
class Cost {
|
public class Cost {
|
||||||
public enum DeferredUDC {
|
public enum DeferredUDC {
|
||||||
NONE, COPY_INIT_OF_CLASS, INIT_BY_CONVERSION, LIST_INIT_OF_CLASS, DIRECT_LIST_INIT_OF_CLASS
|
NONE, COPY_INIT_OF_CLASS, INIT_BY_CONVERSION, LIST_INIT_OF_CLASS, DIRECT_LIST_INIT_OF_CLASS
|
||||||
}
|
}
|
||||||
enum Rank {
|
public enum Rank {
|
||||||
IDENTITY, 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
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,12 +253,14 @@ public class SemanticUtil {
|
||||||
t= ((ITypedef) type).getType();
|
t= ((ITypedef) type).getType();
|
||||||
} else if (type instanceof IQualifierType) {
|
} else if (type instanceof IQualifierType) {
|
||||||
final IQualifierType qt = (IQualifierType) type;
|
final IQualifierType qt = (IQualifierType) type;
|
||||||
|
final IType qttgt = qt.getType();
|
||||||
if (allcvq || cvtype) {
|
if (allcvq || cvtype) {
|
||||||
t= qt.getType();
|
t= qttgt;
|
||||||
} else if (tdef) {
|
} else if (tdef) {
|
||||||
t= getNestedType(qt.getType(), options);
|
t= getNestedType(qttgt, options);
|
||||||
t= addQualifiers(t, qt.isConst(), qt.isVolatile());
|
if (t == qttgt)
|
||||||
return t;
|
return qt;
|
||||||
|
return addQualifiers(t, qt.isConst(), qt.isVolatile());
|
||||||
}
|
}
|
||||||
} else if (type instanceof IArrayType) {
|
} else if (type instanceof IArrayType) {
|
||||||
final IArrayType atype= (IArrayType) type;
|
final IArrayType atype= (IArrayType) type;
|
||||||
|
|
Loading…
Add table
Reference in a new issue