mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-13 10:42:05 +00:00
Some cleanups to the declaration/checking of overloaded operators in C++. Thanks to Sebastian for the review
llvm-svn: 58986
This commit is contained in:
parent
bba5c7c629
commit
6cf0806e75
@ -1316,15 +1316,27 @@ DIAG(err_operator_overload_static, ERROR,
|
||||
DIAG(err_operator_overload_default_arg, ERROR,
|
||||
"a parameter of an overloaded operator cannot have a default argument")
|
||||
DIAG(err_operator_overload_must_be_unary, ERROR,
|
||||
"overloaded operator '%0' must be a unary operator (has %1 parameter%2)")
|
||||
"overloaded operator '%0' must be a unary operator (has %1 parameter)")
|
||||
DIAG(err_operator_overload_must_be_binary, ERROR,
|
||||
"overloaded operator '%0' must be a binary operator (has %1 parameter%2)")
|
||||
"overloaded operator '%0' must be a binary operator (has %1 parameter)")
|
||||
DIAG(err_operator_overload_must_be_unary_or_binary, ERROR,
|
||||
"overloaded operator '%0' must be a unary or binary operator (has %1 parameter%2)")
|
||||
"overloaded operator '%0' must be a unary or binary operator (has %1 parameter)")
|
||||
DIAG(err_operator_overload_must_be_unary_plural, ERROR,
|
||||
"overloaded operator '%0' must be a unary operator (has %1 parameters)")
|
||||
DIAG(err_operator_overload_must_be_binary_plural, ERROR,
|
||||
"overloaded operator '%0' must be a binary operator (has %1 parameters)")
|
||||
DIAG(err_operator_overload_must_be_unary_or_binary_plural, ERROR,
|
||||
"overloaded operator '%0' must be a unary or binary operator (has %1 parameters)")
|
||||
DIAG(err_operator_overload_must_be_member, ERROR,
|
||||
"overloaded operator '%0' must be a non-static member function")
|
||||
DIAG(err_operator_overload_post_incdec_must_be_int, ERROR,
|
||||
"%0parameter of overloaded post-%1 operator must have type 'int' (not '%2')")
|
||||
DIAG(err_operator_overload_post_inc_must_be_int, ERROR,
|
||||
"second parameter of overloaded post-increment operator must have type 'int' (not '%0')")
|
||||
DIAG(err_operator_overload_post_dec_must_be_int, ERROR,
|
||||
"second parameter of overloaded post-decrement operator must have type 'int' (not '%0')")
|
||||
DIAG(err_operator_overload_post_inc_must_be_int_member, ERROR,
|
||||
"parameter of overloaded post-increment operator must have type 'int' (not '%0')")
|
||||
DIAG(err_operator_overload_post_dec_must_be_int_member, ERROR,
|
||||
"parameter of overloaded post-decrement operator must have type 'int' (not '%0')")
|
||||
DIAG(err_operator_missing_type_specifier, ERROR,
|
||||
"missing type specifier after 'operator'")
|
||||
|
||||
|
@ -11,58 +11,93 @@
|
||||
// all of the overloadable C++ operators.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// @file OperatorKinds.def
|
||||
///
|
||||
/// In this file, each of the overloadable C++ operators is enumerated
|
||||
/// with either the OVERLOADED_OPERATOR or OVERLOADED_OPERATOR_MULTI
|
||||
/// macro, each of which can be specified by the code including this
|
||||
/// file. OVERLOADED_OPERATOR is used for single-token operators
|
||||
/// (e.g., "+"), and has six arguments:
|
||||
///
|
||||
/// Name: The name of the token. OO_Name will be the name of the
|
||||
/// corresponding enumerator in OverloadedOperatorKind in
|
||||
/// OperatorKinds.h.
|
||||
///
|
||||
/// Spelling: A string that provides a canonical spelling for the
|
||||
/// operator, e.g., "operator+".
|
||||
///
|
||||
/// Token: The name of the token that specifies the operator, e.g.,
|
||||
/// "plus" for operator+ or "greatergreaterequal" for
|
||||
/// "operator>>=". With a "kw_" prefix, the token name can be used as
|
||||
/// an enumerator into the TokenKind enumeration.
|
||||
///
|
||||
/// Unary: True if the operator can be declared as a unary operator.
|
||||
///
|
||||
/// Binary: True if the operator can be declared as a binary
|
||||
/// operator. Note that some operators (e.g., "operator+" and
|
||||
/// "operator*") can be both unary and binary.
|
||||
///
|
||||
/// MemberOnly: True if this operator can only be declared as a
|
||||
/// non-static member function. False if the operator can be both a
|
||||
/// non-member function and a non-static member function.
|
||||
///
|
||||
/// OVERLOADED_OPERATOR_MULTI is used to enumerate the multi-token
|
||||
/// overloaded operator names, e.g., "operator delete []". The macro
|
||||
/// has all of the parameters of OVERLOADED_OPERATOR except Token,
|
||||
/// which is omitted.
|
||||
|
||||
#ifndef OVERLOADED_OPERATOR
|
||||
# define OVERLOADED_OPERATOR(Name,Spelling,Token)
|
||||
# define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)
|
||||
#endif
|
||||
|
||||
#ifndef OVERLOADED_OPERATOR_MULTI
|
||||
# define OVERLOADED_OPERATOR_MULTI(Name,Spelling) \
|
||||
OVERLOADED_OPERATOR(Name,Spelling,unknown)
|
||||
# define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) \
|
||||
OVERLOADED_OPERATOR(Name,Spelling,unknown,Unary,Binary,MemberOnly)
|
||||
#endif
|
||||
|
||||
OVERLOADED_OPERATOR_MULTI(New , "operator new")
|
||||
OVERLOADED_OPERATOR_MULTI(Delete , "operator delete")
|
||||
OVERLOADED_OPERATOR_MULTI(Array_New , "operator new[]")
|
||||
OVERLOADED_OPERATOR_MULTI(Array_Delete , "operator delete[]")
|
||||
OVERLOADED_OPERATOR(Plus , "operator+" , plus)
|
||||
OVERLOADED_OPERATOR(Minus , "operator-" , minus)
|
||||
OVERLOADED_OPERATOR(Star , "operator*" , star)
|
||||
OVERLOADED_OPERATOR(Slash , "operator/" , slash)
|
||||
OVERLOADED_OPERATOR(Percent , "operator%" , percent)
|
||||
OVERLOADED_OPERATOR(Caret , "operator^" , caret)
|
||||
OVERLOADED_OPERATOR(Amp , "operator&" , amp)
|
||||
OVERLOADED_OPERATOR(Pipe , "operator|" , pipe)
|
||||
OVERLOADED_OPERATOR(Tilde , "operator~" , tilde)
|
||||
OVERLOADED_OPERATOR(Exclaim , "operator!" , exclaim)
|
||||
OVERLOADED_OPERATOR(Equal , "operator=" , equal)
|
||||
OVERLOADED_OPERATOR(Less , "operator<" , less)
|
||||
OVERLOADED_OPERATOR(Greater , "operator>" , greater)
|
||||
OVERLOADED_OPERATOR(PlusEqual , "operator+=" , plusequal)
|
||||
OVERLOADED_OPERATOR(MinusEqual , "operator-=" , minusequal)
|
||||
OVERLOADED_OPERATOR(StarEqual , "operator*=" , starequal)
|
||||
OVERLOADED_OPERATOR(SlashEqual , "operator/=" , slashequal)
|
||||
OVERLOADED_OPERATOR(PercentEqual , "operator%=" , percentequal)
|
||||
OVERLOADED_OPERATOR(CaretEqual , "operator^=" , caretequal)
|
||||
OVERLOADED_OPERATOR(AmpEqual , "operator&=" , ampequal)
|
||||
OVERLOADED_OPERATOR(PipeEqual , "operator|=" , pipeequal)
|
||||
OVERLOADED_OPERATOR(LessLess , "operator<<" , lessless)
|
||||
OVERLOADED_OPERATOR(GreaterGreater , "operator>>" , greatergreater)
|
||||
OVERLOADED_OPERATOR(LessLessEqual , "operator<<=" , lesslessequal)
|
||||
OVERLOADED_OPERATOR(GreaterGreaterEqual , "operator>>=" , greatergreaterequal)
|
||||
OVERLOADED_OPERATOR(EqualEqual , "operator==" , equalequal)
|
||||
OVERLOADED_OPERATOR(ExclaimEqual , "operator!=" , exclaimequal)
|
||||
OVERLOADED_OPERATOR(LessEqual , "operator<=" , lessequal)
|
||||
OVERLOADED_OPERATOR(GreaterEqual , "operator>=" , greaterequal)
|
||||
OVERLOADED_OPERATOR(AmpAmp , "operator&&" , ampamp)
|
||||
OVERLOADED_OPERATOR(PipePipe , "operator||" , pipepipe)
|
||||
OVERLOADED_OPERATOR(PlusPlus , "operator++" , plusplus)
|
||||
OVERLOADED_OPERATOR(MinusMinus , "operator--" , minusminus)
|
||||
OVERLOADED_OPERATOR(Comma , "operator," , comma)
|
||||
OVERLOADED_OPERATOR(ArrowStar , "operator->*" , arrowstar)
|
||||
OVERLOADED_OPERATOR(Arrow , "operator->" , arrow)
|
||||
OVERLOADED_OPERATOR_MULTI(Call , "operator()")
|
||||
OVERLOADED_OPERATOR_MULTI(Subscript , "operator[]")
|
||||
OVERLOADED_OPERATOR_MULTI(New , "operator new" , true , true , false)
|
||||
OVERLOADED_OPERATOR_MULTI(Delete , "operator delete" , true , true , false)
|
||||
OVERLOADED_OPERATOR_MULTI(Array_New , "operator new[]" , true , true , false)
|
||||
OVERLOADED_OPERATOR_MULTI(Array_Delete , "operator delete[]" , true , true , false)
|
||||
OVERLOADED_OPERATOR(Plus , "operator+" , plus , true , true , false)
|
||||
OVERLOADED_OPERATOR(Minus , "operator-" , minus , true , true , false)
|
||||
OVERLOADED_OPERATOR(Star , "operator*" , star , true , true , false)
|
||||
OVERLOADED_OPERATOR(Slash , "operator/" , slash , false, true , false)
|
||||
OVERLOADED_OPERATOR(Percent , "operator%" , percent , false, true , false)
|
||||
OVERLOADED_OPERATOR(Caret , "operator^" , caret , false, true , false)
|
||||
OVERLOADED_OPERATOR(Amp , "operator&" , amp , true , true , false)
|
||||
OVERLOADED_OPERATOR(Pipe , "operator|" , pipe , false, true , false)
|
||||
OVERLOADED_OPERATOR(Tilde , "operator~" , tilde , true , false, false)
|
||||
OVERLOADED_OPERATOR(Exclaim , "operator!" , exclaim , true , false, false)
|
||||
OVERLOADED_OPERATOR(Equal , "operator=" , equal , false, true , true)
|
||||
OVERLOADED_OPERATOR(Less , "operator<" , less , false, true , false)
|
||||
OVERLOADED_OPERATOR(Greater , "operator>" , greater , false, true , false)
|
||||
OVERLOADED_OPERATOR(PlusEqual , "operator+=" , plusequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(MinusEqual , "operator-=" , minusequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(StarEqual , "operator*=" , starequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(SlashEqual , "operator/=" , slashequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(PercentEqual , "operator%=" , percentequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(CaretEqual , "operator^=" , caretequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(AmpEqual , "operator&=" , ampequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(PipeEqual , "operator|=" , pipeequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(LessLess , "operator<<" , lessless , false, true , false)
|
||||
OVERLOADED_OPERATOR(GreaterGreater , "operator>>" , greatergreater , false, true , false)
|
||||
OVERLOADED_OPERATOR(LessLessEqual , "operator<<=" , lesslessequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(GreaterGreaterEqual , "operator>>=" , greatergreaterequal, false, true , false)
|
||||
OVERLOADED_OPERATOR(EqualEqual , "operator==" , equalequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(ExclaimEqual , "operator!=" , exclaimequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(LessEqual , "operator<=" , lessequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(GreaterEqual , "operator>=" , greaterequal , false, true , false)
|
||||
OVERLOADED_OPERATOR(AmpAmp , "operator&&" , ampamp , false, true , false)
|
||||
OVERLOADED_OPERATOR(PipePipe , "operator||" , pipepipe , false, true , false)
|
||||
OVERLOADED_OPERATOR(PlusPlus , "operator++" , plusplus , true , true , false)
|
||||
OVERLOADED_OPERATOR(MinusMinus , "operator--" , minusminus , true , true , false)
|
||||
OVERLOADED_OPERATOR(Comma , "operator," , comma , false, true , false)
|
||||
OVERLOADED_OPERATOR(ArrowStar , "operator->*" , arrowstar , false, true , false)
|
||||
OVERLOADED_OPERATOR(Arrow , "operator->" , arrow , true , false, true)
|
||||
OVERLOADED_OPERATOR_MULTI(Call , "operator()" , true , true , true)
|
||||
OVERLOADED_OPERATOR_MULTI(Subscript , "operator[]" , false, true , true)
|
||||
|
||||
#undef OVERLOADED_OPERATOR_MULTI
|
||||
#undef OVERLOADED_OPERATOR
|
||||
|
@ -20,7 +20,8 @@ namespace clang {
|
||||
/// C++ overloaded operators.
|
||||
enum OverloadedOperatorKind {
|
||||
OO_None, //< Not an overloaded operator
|
||||
#define OVERLOADED_OPERATOR(Name,Spelling,Token) OO_##Name,
|
||||
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
|
||||
OO_##Name,
|
||||
#include "clang/Basic/OperatorKinds.def"
|
||||
NUM_OVERLOADED_OPERATORS
|
||||
};
|
||||
|
@ -165,7 +165,7 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
|
||||
/// 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"
|
||||
|
@ -515,9 +515,9 @@ IdentifierInfo *Parser::MaybeParseOperatorFunctionId() {
|
||||
}
|
||||
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:
|
||||
|
@ -1801,83 +1801,16 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
|
||||
(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 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user