aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td5
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaOverload.cpp29
-rw-r--r--test/SemaCXX/ambiguous-builtin-unary-operator.cpp18
4 files changed, 40 insertions, 14 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index b81278f037..252cfd2718 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -786,7 +786,10 @@ def err_ovl_template_candidate : Note<
"candidate function template specialization %0">;
def err_ovl_candidate_deleted : Note<
"candidate function has been explicitly %select{made unavailable|deleted}0">;
-def err_ovl_builtin_candidate : Note<"built-in candidate operator %2 (%0, %1)">;
+def err_ovl_builtin_binary_candidate : Note<
+ "built-in candidate operator %0 (%1, %2)">;
+def err_ovl_builtin_unary_candidate : Note<
+ "built-in candidate operator %0 (%1)">;
def err_ovl_no_viable_function_in_init : Error<
"no matching constructor for initialization of %0">;
def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">;
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index a889eeefe8..7b6fa47e28 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -916,7 +916,7 @@ public:
OverloadCandidateSet::iterator& Best);
void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
bool OnlyViable,
- BinaryOperator::Opcode Opc=(BinaryOperator::Opcode)0,
+ const char *Opc=0,
SourceLocation Loc=SourceLocation());
FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 27d34ef434..7744ae7c59 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -3973,7 +3973,7 @@ Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
void
Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
bool OnlyViable,
- BinaryOperator::Opcode Opc,
+ const char *Opc,
SourceLocation OpLoc) {
OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
LastCand = CandidateSet.end();
@@ -4048,20 +4048,22 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
Diag(Cand->Surrogate->getLocation(), diag::err_ovl_surrogate_cand)
<< FnType;
} else if (OnlyViable) {
- assert(Cand->Conversions.size() == 2 &&
+ assert(Cand->Conversions.size() <= 2 &&
"builtin-binary-operator-not-binary");
- Diag(OpLoc, diag::err_ovl_builtin_candidate)
- << Cand->BuiltinTypes.ParamTypes[0]
- << Cand->BuiltinTypes.ParamTypes[1]
- << BinaryOperator::getOpcodeStr(Opc);
+ if (Cand->Conversions.size() == 1)
+ Diag(OpLoc, diag::err_ovl_builtin_unary_candidate)
+ << Opc << Cand->BuiltinTypes.ParamTypes[0];
+ else
+ Diag(OpLoc, diag::err_ovl_builtin_binary_candidate)
+ << Opc << Cand->BuiltinTypes.ParamTypes[0]
+ << Cand->BuiltinTypes.ParamTypes[1];
}
else if (!Cand->Viable && !Reported) {
// Non-viability might be due to ambiguous user-defined conversions,
// needed for built-in operators. Report them as well, but only once
// as we have typically many built-in candidates.
- assert(Cand->Conversions.size() == 2 &&
- "builtin-binary-operator-not-binary");
- for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
+ unsigned NoOperands = Cand->Conversions.size();
+ for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion ||
ICS.ConversionFunctionSet.empty())
@@ -4559,7 +4561,8 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
Diag(OpLoc, diag::err_ovl_ambiguous_oper)
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true,
+ UnaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
case OR_Deleted:
@@ -4733,7 +4736,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
assert(Result.isInvalid() &&
"C++ binary operator overloading is missing candidates!");
if (Result.isInvalid())
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false, Opc, OpLoc);
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false,
+ BinaryOperator::getOpcodeStr(Opc), OpLoc);
return move(Result);
}
@@ -4741,7 +4745,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Diag(OpLoc, diag::err_ovl_ambiguous_oper)
<< BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true, Opc, OpLoc);
+ PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true,
+ BinaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
case OR_Deleted:
diff --git a/test/SemaCXX/ambiguous-builtin-unary-operator.cpp b/test/SemaCXX/ambiguous-builtin-unary-operator.cpp
new file mode 100644
index 0000000000..042546af69
--- /dev/null
+++ b/test/SemaCXX/ambiguous-builtin-unary-operator.cpp
@@ -0,0 +1,18 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+struct A {
+ operator int&();
+};
+
+struct B {
+ operator long&();
+};
+
+struct C : B, A { };
+
+void test(C c) {
+ ++c; // expected-error {{use of overloaded operator '++' is ambiguous}}\
+ // expected-note 4 {{built-in candidate operator ++ (}}
+}
+
+