mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 08:55:25 +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 java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
@ -271,8 +272,17 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
assertNoProblemBindings( col );
|
||||
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
|
||||
{
|
||||
IASTTranslationUnit tu = parse( "class A { int y; }; int A::* x = 0;", ParserLanguage.CPP ); //$NON-NLS-1$
|
||||
|
@ -4543,7 +4553,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// };
|
||||
// Sub::Sub( Other * b ) : Base(b) {}
|
||||
public void testBug95673() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
|
||||
ICPPConstructor ctor= ba.assertNonProblem("Base( Other", 4, ICPPConstructor.class);
|
||||
ICPPConstructor ctor2= ba.assertNonProblem("Base(b)", 4, ICPPConstructor.class);
|
||||
|
@ -4949,7 +4959,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// f1(__null);
|
||||
// }
|
||||
public void testBug240567() throws Exception {
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper bh= getAssertionHelper();
|
||||
bh.assertNonProblem("f1(__null", 2, ICPPFunction.class);
|
||||
}
|
||||
|
||||
|
@ -5298,7 +5308,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// problem5(ptm);
|
||||
// }
|
||||
public void testBug214335() throws Exception {
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper bh= getAssertionHelper();
|
||||
|
||||
IBinding b00= bh.assertProblem("problem1(\"", 8);
|
||||
IBinding b01= bh.assertProblem("problem2(\"", 8);
|
||||
|
@ -5416,7 +5426,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// a=0;
|
||||
// }
|
||||
public void testUsingDirectiveWithNestedClass_Bug209582() throws Exception {
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper bh= getAssertionHelper();
|
||||
|
||||
IBinding b= bh.assertNonProblem("a=", 1);
|
||||
assertEquals("x", b.getScope().getScopeName().toString());
|
||||
|
@ -5435,7 +5445,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// Test foo3 (&bar);
|
||||
// }
|
||||
public void testCastAmbiguity_Bug211756() throws Exception {
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper bh= getAssertionHelper();
|
||||
|
||||
bh.assertNonProblem("foo1", 4);
|
||||
bh.assertNonProblem("foo2", 4);
|
||||
|
@ -5449,7 +5459,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// return 0;
|
||||
// }
|
||||
public void testTemplateIDAmbiguity_Bug104706() throws Exception {
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper bh= getAssertionHelper();
|
||||
|
||||
bh.assertNonProblem("relayIndex <", 10);
|
||||
bh.assertNonProblem("relayIndex >", 10);
|
||||
|
@ -5487,7 +5497,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// func(unqualified);
|
||||
// }
|
||||
public void testScopeOfUsingDelegates_Bug219424() throws Exception {
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper bh= getAssertionHelper();
|
||||
|
||||
bh.assertNonProblem("cl c", 2);
|
||||
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.
|
||||
public void testQualifiedTypedefs_Bug222093() throws Exception{
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper bh= getAssertionHelper();
|
||||
IBinding td= bh.assertProblem("TINT", 4);
|
||||
bh.assertProblem("ns::", 2);
|
||||
}
|
||||
|
@ -5667,7 +5677,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// foo/*k2*/(11.1E1L);
|
||||
// }
|
||||
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'};
|
||||
for(char c : cs) {
|
||||
for(int i=1; i<(c < 'i' ? 4 : 3); i++) {
|
||||
|
@ -5727,7 +5737,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// X::operator int() {}
|
||||
// X::xtint(a); // 2
|
||||
public void testEmptyDeclSpecifier() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertNonProblem("X {", 1, ICPPClassType.class);
|
||||
ba.assertNonProblem("X()", 1, ICPPConstructor.class);
|
||||
ba.assertNonProblem("~X", 2, ICPPMethod.class);
|
||||
|
@ -5832,7 +5842,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// class C;
|
||||
// void func(void (C::*m)(int) const);
|
||||
public void test233889_a() throws Exception {
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper bh= getAssertionHelper();
|
||||
ICPPFunction func= bh.assertNonProblem("func(", 4, ICPPFunction.class);
|
||||
assertEquals(1,func.getParameters().length);
|
||||
IType type= func.getParameters()[0].getType();
|
||||
|
@ -5854,7 +5864,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// func(&C::m2);
|
||||
// }
|
||||
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 fn2= bh.assertNonProblem("func(&C::m2", 4, ICPPFunction.class);
|
||||
assertNotSame(fn1, fn2);
|
||||
|
@ -5875,7 +5885,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// void member4() const volatile { foo(this);/*4*/ }
|
||||
// };
|
||||
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 pt2= ba.assertNonProblem("foo(this);/*2*/", 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*/
|
||||
// }
|
||||
public void testMemberAccessOperator_a() throws Exception {
|
||||
BindingAssertionHelper ba=new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba=getAssertionHelper();
|
||||
ba.assertProblem("foo();/*1*/", 3);
|
||||
ba.assertNonProblem("foo();/*2*/", 3);
|
||||
}
|
||||
|
@ -5927,7 +5937,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// b2->foo();/*2*/
|
||||
// }
|
||||
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 m2= ba.assertNonProblem("foo();/*2*/", 3, ICPPMethod.class);
|
||||
assertEquals(m1.getClassOwner().getName(), "A");
|
||||
|
@ -5943,7 +5953,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// c->foo();/**/ // refers to A::foo
|
||||
// }
|
||||
public void testMemberAccessOperator_c() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertNonProblem("foo();/**/", 3);
|
||||
}
|
||||
|
||||
|
@ -5956,7 +5966,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// c->foo();/**/ // expect problem - foo is not in B
|
||||
// }
|
||||
public void testMemberAccessOperator_d() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertProblem("foo();/**/", 3);
|
||||
}
|
||||
|
||||
|
@ -5972,7 +5982,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// c->foo();/**/ // refers to A::foo
|
||||
// }
|
||||
public void testMemberAccessOperator_e() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertNonProblem("foo();/**/", 3);
|
||||
}
|
||||
|
||||
|
@ -6000,7 +6010,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// f4(s);
|
||||
// }
|
||||
public void testArrayToPointerConversion() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertNonProblem("f1(p)", 2, ICPPFunction.class);
|
||||
ba.assertProblem("f2(q)", 2);
|
||||
ba.assertNonProblem("f3(r)", 2, ICPPFunction.class);
|
||||
|
@ -6100,7 +6110,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// func(y);
|
||||
// }
|
||||
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 func2= helper.assertNonProblem("func(y)", 4, ICPPFunction.class);
|
||||
assertNotSame(func1, func2);
|
||||
|
@ -6119,7 +6129,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// func(y[0]);
|
||||
// }
|
||||
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 func2= helper.assertNonProblem("func(y[0])", 4, ICPPFunction.class);
|
||||
assertNotSame(func1, func2);
|
||||
|
@ -6144,7 +6154,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// void m();//5
|
||||
// };
|
||||
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 m1= helper.assertNonProblem("m();//1", 1, ICPPMethod.class);
|
||||
ICPPMethod m2= helper.assertNonProblem("m();//2", 1, ICPPMethod.class);
|
||||
|
@ -6242,7 +6252,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// f(p);
|
||||
// }
|
||||
public void testFunctionExtraArgument() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertProblem("f(p)", 1);
|
||||
}
|
||||
|
||||
|
@ -6367,7 +6377,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// int y;
|
||||
// };
|
||||
public void testScopeOfClassMember_259460() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertNonProblem("B b", 1, ICPPClassType.class);
|
||||
ba.assertProblem("B p", 1);
|
||||
ba.assertProblem("B method", 1);
|
||||
|
@ -6386,7 +6396,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// };
|
||||
// };
|
||||
public void testScopeOfClassMember_259648() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertNonProblem("GREEN)", 5, IEnumerator.class);
|
||||
ba.assertNonProblem("RED;", 3, IEnumerator.class);
|
||||
ba.assertProblem("GREEN;", 5);
|
||||
|
@ -6404,7 +6414,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// func(*b);
|
||||
// }
|
||||
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 f2= ba.assertNonProblem("func(*b)", 4, ICPPFunction.class);
|
||||
assertNotSame(f1, f2);
|
||||
|
@ -6445,7 +6455,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// (p1 % p2).a; //5
|
||||
// }
|
||||
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; //2", 1, ICPPField.class);
|
||||
ba.assertNonProblem("a; //3", 1, ICPPField.class);
|
||||
|
@ -6474,7 +6484,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// (b + i).a; //6
|
||||
// }
|
||||
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; //2", 1, ICPPField.class);
|
||||
ba.assertNonProblem("a; //3", 1, ICPPField.class);
|
||||
|
@ -6498,7 +6508,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// (++p1).x; //2
|
||||
// }
|
||||
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; //2", 1, ICPPField.class);
|
||||
}
|
||||
|
@ -6516,7 +6526,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// (++p1).x; //2
|
||||
// }
|
||||
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; //2", 1, ICPPField.class);
|
||||
}
|
||||
|
@ -6547,7 +6557,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// (~b).xx; // 6
|
||||
// }
|
||||
public void testOverloadedUnaryOperator_259927_5() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
for(int i = 1; i <=6; i++)
|
||||
ba.assertNonProblem("xx; // "+i, 2, ICPPField.class);
|
||||
}
|
||||
|
@ -6578,7 +6588,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// (~b).xx; // 6
|
||||
//}
|
||||
public void testOverloadedUnaryOperator_259927_6() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
for(int i = 1; i <=6; i++)
|
||||
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
|
||||
// };
|
||||
public void testOrderOfAmbiguityResolution_259373() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ICPPVariable a= ba.assertNonProblem("a;", 1);
|
||||
assertInstance(a.getType(), IPointerType.class);
|
||||
ICPPVariable b= ba.assertNonProblem("b;", 1);
|
||||
|
@ -6780,7 +6790,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// f(a());
|
||||
// }
|
||||
public void testBug263152_1() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertProblem("f(a())", 1);
|
||||
}
|
||||
|
||||
|
@ -6796,7 +6806,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// p.m(a());
|
||||
// }
|
||||
public void testBug263152_2() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertNonProblem("m(a())", 1, ICPPMethod.class);
|
||||
}
|
||||
|
||||
|
@ -6807,7 +6817,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// }
|
||||
// };
|
||||
public void _testInstanceMemberInStaticMethod_263154() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertProblem("a =", 1);
|
||||
}
|
||||
|
||||
|
@ -6843,7 +6853,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// f(s);
|
||||
// }
|
||||
public void testPointerToNonPointerConversion_263159() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertProblem("f(p)", 1);
|
||||
ba.assertProblem("f(q)", 1);
|
||||
ba.assertProblem("f(r)", 1);
|
||||
|
@ -6860,7 +6870,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// fia(0);
|
||||
// }
|
||||
public void testNonPointerToPointerConversion_263707() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertProblem("fip(1)", 3);
|
||||
ba.assertProblem("fia(1)", 3);
|
||||
ba.assertNonProblem("fip(0)", 3, ICPPFunction.class);
|
||||
|
@ -6982,7 +6992,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// f(!p);
|
||||
// }
|
||||
public void testTypeOfNotExpression_265779() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertNonProblem("f(!p)", 1);
|
||||
}
|
||||
|
||||
|
@ -7105,7 +7115,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// (x + 1.0).b; //3
|
||||
// }
|
||||
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; //2", 1, ICPPField.class);
|
||||
ba.assertNonProblem("b; //3", 1, ICPPField.class);
|
||||
|
@ -7126,7 +7136,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// (x + 1.0).a; //2
|
||||
// }
|
||||
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; //2", 1, ICPPField.class);
|
||||
}
|
||||
|
@ -7140,7 +7150,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// test(c);
|
||||
// }
|
||||
public void testInvalidUserDefinedConversion_Bug269729() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertProblem("test(c)", 4);
|
||||
}
|
||||
|
||||
|
@ -7174,14 +7184,14 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// struct A;
|
||||
// A a;
|
||||
public void testForwardDeclarationAfterUsing_271236() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertNonProblem("A a;", 1, ICPPClassType.class);
|
||||
}
|
||||
|
||||
// template <class T> class Moo;
|
||||
// bool getFile(Moo <class Foo> & res);
|
||||
public void testScopeOfClassFwdDecl_270831() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ICPPClassType t= ba.assertNonProblem("Foo", 3, ICPPClassType.class);
|
||||
IScope scope= t.getScope();
|
||||
assertEquals(EScopeKind.eGlobal, scope.getKind());
|
||||
|
@ -7349,7 +7359,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// f(l1);
|
||||
// }
|
||||
public void testEnumToIntConversion_285368() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ICPPFunction f1 = ba.assertNonProblem("f(i1)", 1, ICPPFunction.class);
|
||||
IType t1 = f1.getType().getParameterTypes()[0];
|
||||
assertTrue(t1 instanceof ICPPBasicType);
|
||||
|
@ -7369,7 +7379,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
|
||||
// typedef enum enum_name enum_name;
|
||||
public void testTypedefRecursion_285457() throws Exception {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ba.assertProblem("enum_name", 9);
|
||||
}
|
||||
|
||||
|
@ -8650,7 +8660,7 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// Y* m(Y*);//3
|
||||
// };
|
||||
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 m1= helper.assertNonProblem("m(X*);//1", 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;
|
||||
public void testInlineNamespaceLookup_324096() throws Exception {
|
||||
String code= getAboveComment();
|
||||
parseAndCheckBindings(code);
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// 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.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.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
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.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.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,
|
||||
IASTAmbiguityParent {
|
||||
|
||||
private IASTExpression condition;
|
||||
private IASTExpression negative;
|
||||
private IASTExpression positive;
|
||||
private IASTExpression fCondition;
|
||||
private IASTExpression fPositive;
|
||||
private IASTExpression fNegative;
|
||||
private IType fType;
|
||||
private ValueCategory fValueCategory;
|
||||
|
||||
|
||||
public CPPASTConditionalExpression() {
|
||||
|
@ -43,20 +64,20 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
|||
|
||||
public CPPASTConditionalExpression copy() {
|
||||
CPPASTConditionalExpression copy = new CPPASTConditionalExpression();
|
||||
copy.setLogicalConditionExpression(condition == null ? null : condition.copy());
|
||||
copy.setPositiveResultExpression(positive == null ? null : positive.copy());
|
||||
copy.setNegativeResultExpression(negative == null ? null : negative.copy());
|
||||
copy.setLogicalConditionExpression(fCondition == null ? null : fCondition.copy());
|
||||
copy.setPositiveResultExpression(fPositive == null ? null : fPositive.copy());
|
||||
copy.setNegativeResultExpression(fNegative == null ? null : fNegative.copy());
|
||||
copy.setOffsetAndLength(this);
|
||||
return copy;
|
||||
}
|
||||
|
||||
public IASTExpression getLogicalConditionExpression() {
|
||||
return condition;
|
||||
return fCondition;
|
||||
}
|
||||
|
||||
public void setLogicalConditionExpression(IASTExpression expression) {
|
||||
assertNotFrozen();
|
||||
condition = expression;
|
||||
fCondition = expression;
|
||||
if (expression != null) {
|
||||
expression.setParent(this);
|
||||
expression.setPropertyInParent(LOGICAL_CONDITION);
|
||||
|
@ -64,12 +85,12 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
|||
}
|
||||
|
||||
public IASTExpression getPositiveResultExpression() {
|
||||
return positive;
|
||||
return fPositive;
|
||||
}
|
||||
|
||||
public void setPositiveResultExpression(IASTExpression expression) {
|
||||
assertNotFrozen();
|
||||
this.positive = expression;
|
||||
this.fPositive = expression;
|
||||
if (expression != null) {
|
||||
expression.setParent(this);
|
||||
expression.setPropertyInParent(POSITIVE_RESULT);
|
||||
|
@ -77,12 +98,12 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
|||
}
|
||||
|
||||
public IASTExpression getNegativeResultExpression() {
|
||||
return negative;
|
||||
return fNegative;
|
||||
}
|
||||
|
||||
public void setNegativeResultExpression(IASTExpression expression) {
|
||||
assertNotFrozen();
|
||||
this.negative = expression;
|
||||
this.fNegative = expression;
|
||||
if (expression != null) {
|
||||
expression.setParent(this);
|
||||
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( positive != null ) if( !positive.accept( action ) ) return false;
|
||||
if( negative != null ) if( !negative.accept( action ) ) return false;
|
||||
if (fCondition != null && !fCondition.accept(action))
|
||||
return false;
|
||||
if (fPositive != null && !fPositive.accept(action))
|
||||
return false;
|
||||
if (fNegative != null && !fNegative.accept(action))
|
||||
return false;
|
||||
|
||||
if( action.shouldVisitExpressions ){
|
||||
switch( action.leave( this ) ){
|
||||
case ASTVisitor.PROCESS_ABORT : return false;
|
||||
case ASTVisitor.PROCESS_SKIP : return true;
|
||||
default : break;
|
||||
}
|
||||
}
|
||||
if (action.shouldVisitExpressions && action.leave(this) == ASTVisitor.PROCESS_ABORT)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void replace(IASTNode child, IASTNode other) {
|
||||
if( child == condition )
|
||||
{
|
||||
other.setPropertyInParent( child.getPropertyInParent() );
|
||||
other.setParent( child.getParent() );
|
||||
condition = (IASTExpression) other;
|
||||
}
|
||||
if( child == positive )
|
||||
{
|
||||
other.setPropertyInParent( child.getPropertyInParent() );
|
||||
other.setParent( child.getParent() );
|
||||
positive = (IASTExpression) other;
|
||||
}
|
||||
if( child == negative )
|
||||
{
|
||||
other.setPropertyInParent( child.getPropertyInParent() );
|
||||
other.setParent( child.getParent() );
|
||||
negative = (IASTExpression) other;
|
||||
}
|
||||
public void replace(IASTNode child, IASTNode other) {
|
||||
if (child == fCondition) {
|
||||
other.setPropertyInParent(child.getPropertyInParent());
|
||||
other.setParent(child.getParent());
|
||||
fCondition = (IASTExpression) other;
|
||||
}
|
||||
if (child == fPositive) {
|
||||
other.setPropertyInParent(child.getPropertyInParent());
|
||||
other.setParent(child.getParent());
|
||||
fPositive = (IASTExpression) other;
|
||||
}
|
||||
if (child == fNegative) {
|
||||
other.setPropertyInParent(child.getPropertyInParent());
|
||||
other.setParent(child.getParent());
|
||||
fNegative = (IASTExpression) other;
|
||||
}
|
||||
}
|
||||
|
||||
public IType getExpressionType() {
|
||||
evaluate();
|
||||
return fType;
|
||||
}
|
||||
|
||||
// mstodo conditional operator (type)
|
||||
public IType getExpressionType() {
|
||||
IASTExpression positiveExpression = getPositiveResultExpression();
|
||||
if (positiveExpression == null) {
|
||||
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() {
|
||||
return PRVALUE;
|
||||
evaluate();
|
||||
return fValueCategory;
|
||||
}
|
||||
|
||||
public boolean isLValue() {
|
||||
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;
|
||||
consume(IToken.t_decltype);
|
||||
consume(IToken.tLPAREN);
|
||||
typeofExpression= unaryExpression(CastExprCtx.eNotBExpr);
|
||||
typeofExpression= expression();
|
||||
endOffset= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
||||
|
||||
encounteredTypename= true;
|
||||
|
|
|
@ -70,7 +70,12 @@ public enum OverloadableOperator {
|
|||
NEW("new"),
|
||||
DELETE_ARRAY("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;
|
||||
|
||||
|
|
|
@ -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.IType;
|
||||
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.ICPPFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
|
@ -217,6 +218,11 @@ class BuiltinOperators {
|
|||
case NOT:
|
||||
addFunction(BOOL, BOOL);
|
||||
break;
|
||||
|
||||
case CONDITIONAL_OPERATOR:
|
||||
binaryPromotedArithmetic(true, ReturnType.CONVERT);
|
||||
conditional();
|
||||
break;
|
||||
}
|
||||
|
||||
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) {
|
||||
addFunction(returnType, new IType[] {p1});
|
||||
}
|
||||
|
@ -556,7 +575,11 @@ class BuiltinOperators {
|
|||
private boolean isEnumeration(IType type) {
|
||||
return type instanceof IEnumeration;
|
||||
}
|
||||
|
||||
|
||||
private boolean isScopedEnumeration(IType type) {
|
||||
return type instanceof ICPPEnumeration && ((ICPPEnumeration) type).isScoped();
|
||||
}
|
||||
|
||||
private boolean isPointer(IType type) {
|
||||
return type instanceof IPointerType && !(type instanceof ICPPPointerToMemberType);
|
||||
}
|
||||
|
|
|
@ -2825,7 +2825,7 @@ public class CPPSemantics {
|
|||
*/
|
||||
|
||||
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)
|
||||
break;
|
||||
|
||||
|
@ -2852,7 +2852,7 @@ public class CPPSemantics {
|
|||
IASTInitializerClause[] args = {exp.getArrayExpression(), exp.getArgument()};
|
||||
IType type = exp.getArrayExpression().getExpressionType();
|
||||
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) {
|
||||
|
@ -2864,7 +2864,7 @@ public class CPPSemantics {
|
|||
}
|
||||
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) {
|
||||
|
@ -2888,14 +2888,14 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
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) {
|
||||
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
|
||||
IType classType = getNestedClassType(exp);
|
||||
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) {
|
||||
|
@ -3063,7 +3063,7 @@ public class CPPSemantics {
|
|||
if (!isUserDefined(type))
|
||||
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) {
|
||||
|
@ -3081,14 +3081,25 @@ public class CPPSemantics {
|
|||
if (!isUserDefined(op1type) && !isUserDefined(op2type))
|
||||
return null;
|
||||
|
||||
IASTExpression[] args = new IASTExpression[] { op1, op2 };
|
||||
NonMemberMode lookupNonMember = NonMemberMode.none;
|
||||
if (exp.getOperator() != IASTBinaryExpression.op_assign) {
|
||||
lookupNonMember= NonMemberMode.limited;
|
||||
final IASTExpression[] args = new IASTExpression[] { op1, op2 };
|
||||
final LookupMode lookupNonMember;
|
||||
if (exp.getOperator() == IASTBinaryExpression.op_assign) {
|
||||
lookupNonMember = LookupMode.NO_GLOBALS;
|
||||
} else {
|
||||
lookupNonMember= LookupMode.LIMITED_GLOBALS;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the operator,() function that would apply to the two given arguments.
|
||||
|
@ -3106,12 +3117,12 @@ public class CPPSemantics {
|
|||
dummy.setParent(first);
|
||||
|
||||
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,
|
||||
OverloadableOperator operator, NonMemberMode mode) {
|
||||
OverloadableOperator operator, LookupMode mode) {
|
||||
ICPPClassType callToObjectOfClassType= null;
|
||||
IType type2= null;
|
||||
if (args.length >= 2 && args[1] instanceof IASTExpression) {
|
||||
|
@ -3158,9 +3169,9 @@ public class CPPSemantics {
|
|||
LookupData funcData = new LookupData(funcName);
|
||||
funcData.setFunctionArguments(true, args);
|
||||
funcData.ignoreMembers = true; // (13.3.1.2.3)
|
||||
if (mode != NonMemberMode.none || callToObjectOfClassType != null) {
|
||||
if (mode != LookupMode.NO_GLOBALS || callToObjectOfClassType != null) {
|
||||
try {
|
||||
if (mode != NonMemberMode.none) {
|
||||
if (mode != LookupMode.NO_GLOBALS) {
|
||||
IScope scope = CPPVisitor.getContainingScope(parent);
|
||||
if (scope == null)
|
||||
return null;
|
||||
|
@ -3195,7 +3206,7 @@ public class CPPSemantics {
|
|||
|
||||
// 13.3.1.2.3
|
||||
// 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)) {
|
||||
IEnumeration enum1= 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.parser.util.CharArrayUtils;
|
||||
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.cpp.CPPASTName;
|
||||
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.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.semantics.Cost.DeferredUDC;
|
||||
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.
|
||||
*/
|
||||
public class Conversions {
|
||||
enum UDCMode {ALLOWED, FORBIDDEN, DEFER}
|
||||
enum Context {ORDINARY, IMPLICIT_OBJECT, FIRST_PARAM_OF_DIRECT_COPY_CTOR}
|
||||
public enum UDCMode {ALLOWED, FORBIDDEN, DEFER}
|
||||
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[] 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.
|
||||
|
||||
// 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) {
|
||||
Cost cost= nonReferenceConversion(valueCat, cv2T2, T1, udc, false);
|
||||
if (!isImplicitWithoutRefQualifier && cost.converts()) {
|
||||
|
@ -808,38 +810,25 @@ public class Conversions {
|
|||
|
||||
// 4.2 array to pointer conversion
|
||||
if (source instanceof IArrayType) {
|
||||
final IArrayType arrayType= (IArrayType) source;
|
||||
|
||||
boolean isConverted= false;
|
||||
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
|
||||
if (!(targetPtrTgt instanceof IQualifierType) || !((IQualifierType) targetPtrTgt).isConst()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
source = unqualifyStringLiteral(source, (IPointerType) target, cost);
|
||||
}
|
||||
if (!isConverted) {
|
||||
source = new CPPPointerType(getNestedType(arrayType.getType(), TDEF));
|
||||
if (!(source instanceof IPointerType)) {
|
||||
source = new CPPPointerType(getNestedType(((IArrayType) source).getType(), TDEF));
|
||||
}
|
||||
} else if (source instanceof IFunctionType) {
|
||||
// 4.3 function to pointer conversion
|
||||
source = new CPPPointerType(source);
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
@ -851,6 +840,35 @@ public class Conversions {
|
|||
cost.target= 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
|
||||
|
@ -870,22 +888,12 @@ public class Conversions {
|
|||
final int cmp= compareQualifications(t, s); // is t more qualified than s?
|
||||
if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
|
||||
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 sPtr = (IPointerType) s;
|
||||
if (haveMemberPtrConflict(sPtr, tPtr))
|
||||
return false;
|
||||
|
||||
constInEveryCV2k &= (firstPointer || tPtr.isConst());
|
||||
s= sPtr.getType();
|
||||
t= tPtr.getType();
|
||||
|
@ -912,6 +920,22 @@ public class Conversions {
|
|||
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.
|
||||
*
|
||||
|
@ -1041,17 +1065,13 @@ public class Conversions {
|
|||
|
||||
if (t instanceof IPointerType) {
|
||||
IPointerType tgtPtr= (IPointerType) t;
|
||||
if (s instanceof CPPBasicType) {
|
||||
// 4.10-1 an integral constant expression of integer type that evaluates to 0 can
|
||||
// be converted to a pointer type
|
||||
// 4.11-1 same for pointer to member
|
||||
IASTExpression exp = ((CPPBasicType) s).getCreatedFromExpression();
|
||||
if (exp != null) {
|
||||
Long val= Value.create(exp, Value.MAX_RECURSION_DEPTH).numericalValue();
|
||||
if (val != null && val == 0) {
|
||||
cost.setRank(Rank.CONVERSION);
|
||||
return true;
|
||||
}
|
||||
// 4.10-1 an integral constant expression of integer type that evaluates to 0 can
|
||||
// be converted to a pointer type
|
||||
// 4.11-1 same for pointer to member
|
||||
if (s instanceof IBasicType) {
|
||||
if (isNullPointerConstant(s)) {
|
||||
cost.setRank(Rank.CONVERSION);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1119,6 +1139,19 @@ public class Conversions {
|
|||
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
|
||||
*/
|
||||
|
@ -1136,4 +1169,112 @@ public class Conversions {
|
|||
}
|
||||
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.
|
||||
*/
|
||||
class Cost {
|
||||
public class Cost {
|
||||
public enum DeferredUDC {
|
||||
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,
|
||||
USER_DEFINED_CONVERSION, ELLIPSIS_CONVERSION, NO_MATCH
|
||||
}
|
||||
|
|
|
@ -253,12 +253,14 @@ public class SemanticUtil {
|
|||
t= ((ITypedef) type).getType();
|
||||
} else if (type instanceof IQualifierType) {
|
||||
final IQualifierType qt = (IQualifierType) type;
|
||||
final IType qttgt = qt.getType();
|
||||
if (allcvq || cvtype) {
|
||||
t= qt.getType();
|
||||
t= qttgt;
|
||||
} else if (tdef) {
|
||||
t= getNestedType(qt.getType(), options);
|
||||
t= addQualifiers(t, qt.isConst(), qt.isVolatile());
|
||||
return t;
|
||||
t= getNestedType(qttgt, options);
|
||||
if (t == qttgt)
|
||||
return qt;
|
||||
return addQualifiers(t, qt.isConst(), qt.isVolatile());
|
||||
}
|
||||
} else if (type instanceof IArrayType) {
|
||||
final IArrayType atype= (IArrayType) type;
|
||||
|
|
Loading…
Add table
Reference in a new issue