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:
|
||||
// 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
|
||||
// built-in operator, which will produce an error message for us.
|
||||
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 {
|
||||
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
|
||||
|
||||
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;
|
||||
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