forked from OSchip/llvm-project
Avoid using the built-in type checker for assignment in C++ when classes are involved. Patch by Vyacheslav Kononenko.
llvm-svn: 72212
This commit is contained in:
parent
7d0479f2c2
commit
027de2adcd
|
@ -4020,6 +4020,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
|
||||||
}
|
}
|
||||||
|
|
||||||
case OR_No_Viable_Function:
|
case OR_No_Viable_Function:
|
||||||
|
// For class as left operand for assignment or compound assigment operator
|
||||||
|
// do not fall through to handling in built-in, but report that no overloaded
|
||||||
|
// assignment operator found
|
||||||
|
if (LHS->getType()->isRecordType() && Opc >= BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign) {
|
||||||
|
Diag(OpLoc, diag::err_ovl_no_viable_oper)
|
||||||
|
<< BinaryOperator::getOpcodeStr(Opc)
|
||||||
|
<< LHS->getSourceRange() << RHS->getSourceRange();
|
||||||
|
return ExprError();
|
||||||
|
}
|
||||||
// No viable function; fall through to handling this as a
|
// No viable function; fall through to handling this as a
|
||||||
// built-in operator, which will produce an error message for us.
|
// built-in operator, which will produce an error message for us.
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
// RUN: clang-cc -fsyntax-only -verify %s
|
||||||
|
struct A {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConvertibleToA {
|
||||||
|
operator A();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConvertibleToConstA {
|
||||||
|
operator const A();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B {
|
||||||
|
B& operator=(B&);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConvertibleToB {
|
||||||
|
operator B();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConvertibleToBref {
|
||||||
|
operator B&();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConvertibleToConstB {
|
||||||
|
operator const B();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConvertibleToConstBref {
|
||||||
|
operator const B&();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct C {
|
||||||
|
int operator=(int); // expected-note{{candidate function}}
|
||||||
|
long operator=(long); // expected-note{{candidate function}}
|
||||||
|
int operator+=(int); // expected-note{{candidate function}}
|
||||||
|
int operator+=(long); // expected-note{{candidate function}}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct D {
|
||||||
|
D& operator+=(const D &);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConvertibleToInt {
|
||||||
|
operator int();
|
||||||
|
};
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
A a, na;
|
||||||
|
const A constA;
|
||||||
|
ConvertibleToA convertibleToA;
|
||||||
|
ConvertibleToConstA convertibleToConstA;
|
||||||
|
|
||||||
|
B b, nb;
|
||||||
|
const B constB;
|
||||||
|
ConvertibleToB convertibleToB;
|
||||||
|
ConvertibleToBref convertibleToBref;
|
||||||
|
ConvertibleToConstB convertibleToConstB;
|
||||||
|
ConvertibleToConstBref convertibleToConstBref;
|
||||||
|
|
||||||
|
C c, nc;
|
||||||
|
const C constC;
|
||||||
|
|
||||||
|
D d, nd;
|
||||||
|
const D constD;
|
||||||
|
|
||||||
|
ConvertibleToInt convertibleToInt;
|
||||||
|
|
||||||
|
na = a;
|
||||||
|
na = constA;
|
||||||
|
na = convertibleToA;
|
||||||
|
na = convertibleToConstA;
|
||||||
|
na += a; // expected-error{{no viable overloaded '+='}}
|
||||||
|
|
||||||
|
nb = b;
|
||||||
|
nb = constB; // expected-error{{no viable overloaded '='}}
|
||||||
|
nb = convertibleToB; // expected-error{{no viable overloaded '='}}
|
||||||
|
nb = convertibleToBref;
|
||||||
|
nb = convertibleToConstB; // expected-error{{no viable overloaded '='}}
|
||||||
|
nb = convertibleToConstBref; // expected-error{{no viable overloaded '='}}
|
||||||
|
|
||||||
|
nc = c;
|
||||||
|
nc = constC;
|
||||||
|
nc = 1;
|
||||||
|
nc = 1L;
|
||||||
|
nc = 1.0; // expected-error{{use of overloaded operator '=' is ambiguous}}
|
||||||
|
nc += 1;
|
||||||
|
nc += 1L;
|
||||||
|
nc += 1.0; // expected-error{{use of overloaded operator '+=' is ambiguous}}
|
||||||
|
|
||||||
|
nd = d;
|
||||||
|
nd += d;
|
||||||
|
nd += constD;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
i = convertibleToInt;
|
||||||
|
i = a; // expected-error{{incompatible type assigning 'struct A', expected 'int'}}
|
||||||
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace S1 {
|
||||||
|
|
||||||
namespace S3 {
|
namespace S3 {
|
||||||
void f() {
|
void f() {
|
||||||
x = 0; // expected-error {{incompatible type assigning 'int', expected 'class B'}}
|
x = 0; // expected-error {{no viable overloaded '='}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,5 +118,5 @@ void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip, ShortRef sr,
|
||||||
// C++ [over.match.open]p4
|
// C++ [over.match.open]p4
|
||||||
|
|
||||||
void test_assign_restrictions(ShortRef& sr) {
|
void test_assign_restrictions(ShortRef& sr) {
|
||||||
sr = (short)0; // expected-error{{incompatible type assigning 'short', expected 'struct ShortRef'}}
|
sr = (short)0; // expected-error{{no viable overloaded '='}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,5 @@ void test() {
|
||||||
|
|
||||||
std::vector<INT> v1;
|
std::vector<INT> v1;
|
||||||
vector<Real> v2;
|
vector<Real> v2;
|
||||||
v1 = v2; // expected-error{{incompatible type assigning 'vector<Real>', expected 'std::vector<INT>'}}
|
v1 = v2; // expected-error{{no viable overloaded '='}}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue