Some cleanups to the declaration/checking of overloaded operators in C++. Thanks to Sebastian for the review
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58986 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index e17f48a..2b9d7e3 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -165,7 +165,7 @@
/// AddOverloadedOperators - Register the name of all C++ overloadable
/// operators ("operator+", "operator[]", etc.)
void IdentifierTable::AddOverloadedOperators() {
-#define OVERLOADED_OPERATOR(Name,Spelling,Token) \
+#define OVERLOADED_OPERATOR(Name,Spelling,Token, Unary, Binary, MemberOnly) \
OverloadedOperators[OO_##Name] = &get(Spelling); \
OverloadedOperators[OO_##Name]->setOverloadedOperatorID(OO_##Name);
#include "clang/Basic/OperatorKinds.def"
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 2fe3bcf..a1fd565 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -515,9 +515,9 @@
}
return &PP.getIdentifierTable().getOverloadedOperator(Op);
-#define OVERLOADED_OPERATOR(Name,Spelling,Token) \
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
case tok::Token: Op = OO_##Name; break;
-#define OVERLOADED_OPERATOR_MULTI(Name,Spelling)
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
#include "clang/Basic/OperatorKinds.def"
case tok::l_paren:
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8bdb389..c10fd8b 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1801,83 +1801,16 @@
}
}
- bool CanBeUnaryOperator = false;
- bool CanBeBinaryOperator = false;
- bool MustBeMemberOperator = false;
+ static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = {
+ { false, false, false }
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ , { Unary, Binary, MemberOnly }
+#include "clang/Basic/OperatorKinds.def"
+ };
- switch (Op) {
- case OO_New:
- case OO_Delete:
- case OO_Array_New:
- case OO_Array_Delete:
- assert(false && "Operators new, new[], delete, and delete[] handled above");
- return true;
-
- // Unary-only operators
- case OO_Arrow:
- MustBeMemberOperator = true;
- // Fall through
-
- case OO_Tilde:
- case OO_Exclaim:
- CanBeUnaryOperator = true;
- break;
-
- // Binary-only operators
- case OO_Equal:
- case OO_Subscript:
- MustBeMemberOperator = true;
- // Fall through
-
- case OO_Slash:
- case OO_Percent:
- case OO_Caret:
- case OO_Pipe:
- case OO_Less:
- case OO_Greater:
- case OO_PlusEqual:
- case OO_MinusEqual:
- case OO_StarEqual:
- case OO_SlashEqual:
- case OO_PercentEqual:
- case OO_CaretEqual:
- case OO_AmpEqual:
- case OO_PipeEqual:
- case OO_LessLess:
- case OO_GreaterGreater:
- case OO_LessLessEqual:
- case OO_GreaterGreaterEqual:
- case OO_EqualEqual:
- case OO_ExclaimEqual:
- case OO_LessEqual:
- case OO_GreaterEqual:
- case OO_AmpAmp:
- case OO_PipePipe:
- case OO_Comma:
- CanBeBinaryOperator = true;
- break;
-
- // Unary or binary operators
- case OO_Amp:
- case OO_Plus:
- case OO_Minus:
- case OO_Star:
- case OO_PlusPlus:
- case OO_MinusMinus:
- case OO_ArrowStar:
- CanBeUnaryOperator = true;
- CanBeBinaryOperator = true;
- break;
-
- case OO_Call:
- MustBeMemberOperator = true;
- break;
-
- case OO_None:
- case NUM_OVERLOADED_OPERATORS:
- assert(false && "Not an overloaded operator!");
- return true;
- }
+ bool CanBeUnaryOperator = OperatorUses[Op][0];
+ bool CanBeBinaryOperator = OperatorUses[Op][1];
+ bool MustBeMemberOperator = OperatorUses[Op][2];
// C++ [over.oper]p8:
// [...] Operator functions cannot have more or fewer parameters
@@ -1890,23 +1823,30 @@
(NumParams < 1) || (NumParams > 2))) {
// We have the wrong number of parameters.
std::string NumParamsStr = (llvm::APSInt(32) = NumParams).toString(10);
- std::string NumParamsPlural;
- if (NumParams != 1)
- NumParamsPlural = "s";
diag::kind DK;
- if (CanBeUnaryOperator && CanBeBinaryOperator)
- DK = diag::err_operator_overload_must_be_unary_or_binary;
- else if (CanBeUnaryOperator)
- DK = diag::err_operator_overload_must_be_unary;
- else if (CanBeBinaryOperator)
- DK = diag::err_operator_overload_must_be_binary;
- else
+ if (CanBeUnaryOperator && CanBeBinaryOperator) {
+ if (NumParams == 1)
+ DK = diag::err_operator_overload_must_be_unary_or_binary;
+ else
+ DK = diag::err_operator_overload_must_be_unary_or_binary;
+ } else if (CanBeUnaryOperator) {
+ if (NumParams == 1)
+ DK = diag::err_operator_overload_must_be_unary;
+ else
+ DK = diag::err_operator_overload_must_be_unary_plural;
+ } else if (CanBeBinaryOperator) {
+ if (NumParams == 1)
+ DK = diag::err_operator_overload_must_be_binary;
+ else
+ DK = diag::err_operator_overload_must_be_binary_plural;
+ } else {
assert(false && "All non-call overloaded operators are unary or binary!");
+ }
Diag(FnDecl->getLocation(), DK,
- FnDecl->getName(), NumParamsStr, NumParamsPlural,
+ FnDecl->getName(), NumParamsStr,
SourceRange(FnDecl->getLocation()));
IsInvalid = true;
}
@@ -1945,11 +1885,19 @@
ParamIsInt = BT->getKind() == BuiltinType::Int;
if (!ParamIsInt) {
- Diag(LastParam->getLocation(),
- diag::err_operator_overload_post_incdec_must_be_int,
- MethodDecl? std::string() : std::string("second "),
- (Op == OO_PlusPlus)? std::string("increment")
- : std::string("decrement"),
+ diag::kind DK;
+ if (Op == OO_PlusPlus) {
+ if (MethodDecl)
+ DK = diag::err_operator_overload_post_inc_must_be_int_member;
+ else
+ DK = diag::err_operator_overload_post_inc_must_be_int;
+ } else {
+ if (MethodDecl)
+ DK = diag::err_operator_overload_post_dec_must_be_int_member;
+ else
+ DK = diag::err_operator_overload_post_dec_must_be_int;
+ }
+ Diag(LastParam->getLocation(), DK,
Context.getCanonicalType(LastParam->getType()).getAsString(),
SourceRange(FnDecl->getLocation()));
IsInvalid = true;