forked from OSchip/llvm-project
Some cleanups for C++ operator overloading
llvm-svn: 59443
This commit is contained in:
parent
9edcc802c3
commit
d69246bd5b
|
@ -1324,31 +1324,34 @@ DIAG(err_ambiguous_derived_to_base_conv, ERROR,
|
|||
|
||||
// C++ operator overloading
|
||||
DIAG(err_operator_overload_needs_class_or_enum, ERROR,
|
||||
"non-member overloaded operator '%0' must have at least one parameter of class or enumeration type (or reference thereof)")
|
||||
"overloaded '%0' must have at least one parameter of class "
|
||||
"or enumeration type")
|
||||
DIAG(err_operator_overload_variadic, ERROR,
|
||||
"overloaded operator cannot be variadic")
|
||||
"overloaded '%0' cannot be variadic")
|
||||
DIAG(err_operator_overload_static, ERROR,
|
||||
"overloaded operator '%0' cannot be a static member function")
|
||||
"overloaded '%0' cannot be a static member function")
|
||||
DIAG(err_operator_overload_default_arg, ERROR,
|
||||
"a parameter of an overloaded operator cannot have a default argument")
|
||||
"parameter of overloaded '%0' cannot have a default argument")
|
||||
DIAG(err_operator_overload_must_be_unary, ERROR,
|
||||
"overloaded operator '%0' must be a unary operator (has %1 parameter)")
|
||||
"overloaded '%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)")
|
||||
"overloaded '%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)")
|
||||
"overloaded '%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)")
|
||||
"overloaded '%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)")
|
||||
"overloaded '%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)")
|
||||
"overloaded '%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")
|
||||
"overloaded '%0' must be a non-static member function")
|
||||
DIAG(err_operator_overload_post_inc_must_be_int, ERROR,
|
||||
"parameter of overloaded post-increment operator must have type 'int' (not '%0')")
|
||||
"parameter of overloaded post-increment operator must have type 'int' "
|
||||
"(not '%0')")
|
||||
DIAG(err_operator_overload_post_dec_must_be_int, ERROR,
|
||||
"parameter of overloaded post-decrement operator must have type 'int' (not '%0')")
|
||||
"parameter of overloaded post-decrement operator must have type 'int' "
|
||||
"(not '%0')")
|
||||
DIAG(err_operator_missing_type_specifier, ERROR,
|
||||
"missing type specifier after 'operator'")
|
||||
|
||||
|
|
|
@ -795,7 +795,7 @@ private:
|
|||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 13.5: Overloaded operators [over.oper]
|
||||
IdentifierInfo *MaybeParseOperatorFunctionId();
|
||||
IdentifierInfo *TryParseOperatorFunctionId();
|
||||
TypeTy *ParseConversionFunctionId();
|
||||
};
|
||||
|
||||
|
|
|
@ -1464,7 +1464,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
SourceLocation OperatorLoc = Tok.getLocation();
|
||||
|
||||
// First try the name of an overloaded operator
|
||||
if (IdentifierInfo *II = MaybeParseOperatorFunctionId()) {
|
||||
if (IdentifierInfo *II = TryParseOperatorFunctionId()) {
|
||||
D.SetIdentifier(II, OperatorLoc);
|
||||
} else {
|
||||
// This must be a conversion function (C++ [class.conv.fct]).
|
||||
|
|
|
@ -149,7 +149,7 @@ Parser::ExprResult Parser::ParseCXXIdExpression() {
|
|||
|
||||
case tok::kw_operator: {
|
||||
SourceLocation OperatorLoc = Tok.getLocation();
|
||||
if (IdentifierInfo *II = MaybeParseOperatorFunctionId()) {
|
||||
if (IdentifierInfo *II = TryParseOperatorFunctionId()) {
|
||||
return Actions.ActOnIdentifierExpr(CurScope, OperatorLoc, *II,
|
||||
Tok.is(tok::l_paren), &SS);
|
||||
}
|
||||
|
@ -519,7 +519,7 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// MaybeParseOperatorFunctionId - Attempts to parse a C++ overloaded
|
||||
/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
|
||||
/// operator name (C++ [over.oper]). If successful, returns the
|
||||
/// predefined identifier that corresponds to that overloaded
|
||||
/// operator. Otherwise, returns NULL and does not consume any tokens.
|
||||
|
@ -534,7 +534,7 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
|
|||
/// ^= &= |= << >> >>= <<= == !=
|
||||
/// <= >= && || ++ -- , ->* ->
|
||||
/// () []
|
||||
IdentifierInfo *Parser::MaybeParseOperatorFunctionId() {
|
||||
IdentifierInfo *Parser::TryParseOperatorFunctionId() {
|
||||
assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
|
||||
|
||||
OverloadedOperatorKind Op = OO_None;
|
||||
|
@ -581,16 +581,12 @@ IdentifierInfo *Parser::MaybeParseOperatorFunctionId() {
|
|||
return &PP.getIdentifierTable().getOverloadedOperator(OO_Subscript);
|
||||
|
||||
default:
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Op == OO_None)
|
||||
return 0;
|
||||
else {
|
||||
ConsumeToken(); // 'operator'
|
||||
ConsumeAnyToken(); // the operator itself
|
||||
return &PP.getIdentifierTable().getOverloadedOperator(Op);
|
||||
}
|
||||
ConsumeToken(); // 'operator'
|
||||
ConsumeAnyToken(); // the operator itself
|
||||
return &PP.getIdentifierTable().getOverloadedOperator(Op);
|
||||
}
|
||||
|
||||
/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Parse/DeclSpec.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include <algorithm> // for std::equal
|
||||
#include <map>
|
||||
|
@ -1825,11 +1826,9 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
|
|||
/// of this overloaded operator is well-formed. If so, returns false;
|
||||
/// otherwise, emits appropriate diagnostics and returns true.
|
||||
bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
|
||||
assert(FnDecl && FnDecl->getOverloadedOperator() != OO_None &&
|
||||
assert(FnDecl && FnDecl->isOverloadedOperator() &&
|
||||
"Expected an overloaded operator declaration");
|
||||
|
||||
bool IsInvalid = false;
|
||||
|
||||
OverloadedOperatorKind Op = FnDecl->getOverloadedOperator();
|
||||
|
||||
// C++ [over.oper]p5:
|
||||
|
@ -1849,39 +1848,27 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
|
|||
// function or be a non-member function and have at least one
|
||||
// parameter whose type is a class, a reference to a class, an
|
||||
// enumeration, or a reference to an enumeration.
|
||||
CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl);
|
||||
if (MethodDecl) {
|
||||
if (MethodDecl->isStatic()) {
|
||||
Diag(FnDecl->getLocation(),
|
||||
diag::err_operator_overload_static,
|
||||
FnDecl->getName(),
|
||||
SourceRange(FnDecl->getLocation()));
|
||||
IsInvalid = true;
|
||||
|
||||
// Pretend this isn't a member function; it'll supress
|
||||
// additional, unnecessary error messages.
|
||||
MethodDecl = 0;
|
||||
}
|
||||
if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) {
|
||||
if (MethodDecl->isStatic())
|
||||
return Diag(FnDecl->getLocation(),
|
||||
diag::err_operator_overload_static,
|
||||
FnDecl->getName());
|
||||
} else {
|
||||
bool ClassOrEnumParam = false;
|
||||
for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
|
||||
Param != FnDecl->param_end(); ++Param) {
|
||||
QualType ParamType = (*Param)->getType();
|
||||
if (const ReferenceType *RefType = ParamType->getAsReferenceType())
|
||||
ParamType = RefType->getPointeeType();
|
||||
for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
|
||||
ParamEnd = FnDecl->param_end();
|
||||
Param != ParamEnd; ++Param) {
|
||||
QualType ParamType = (*Param)->getType().getNonReferenceType();
|
||||
if (ParamType->isRecordType() || ParamType->isEnumeralType()) {
|
||||
ClassOrEnumParam = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ClassOrEnumParam) {
|
||||
Diag(FnDecl->getLocation(),
|
||||
diag::err_operator_overload_needs_class_or_enum,
|
||||
FnDecl->getName(),
|
||||
SourceRange(FnDecl->getLocation()));
|
||||
IsInvalid = true;
|
||||
}
|
||||
if (!ClassOrEnumParam)
|
||||
return Diag(FnDecl->getLocation(),
|
||||
diag::err_operator_overload_needs_class_or_enum,
|
||||
FnDecl->getName());
|
||||
}
|
||||
|
||||
// C++ [over.oper]p8:
|
||||
|
@ -1893,12 +1880,10 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
|
|||
if (Op != OO_Call) {
|
||||
for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
|
||||
Param != FnDecl->param_end(); ++Param) {
|
||||
if (Expr *DefArg = (*Param)->getDefaultArg()) {
|
||||
Diag((*Param)->getLocation(),
|
||||
diag::err_operator_overload_default_arg,
|
||||
DefArg->getSourceRange());
|
||||
IsInvalid = true;
|
||||
}
|
||||
if (Expr *DefArg = (*Param)->getDefaultArg())
|
||||
return Diag((*Param)->getLocation(),
|
||||
diag::err_operator_overload_default_arg,
|
||||
FnDecl->getName(), DefArg->getSourceRange());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1917,13 +1902,14 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
|
|||
// [...] Operator functions cannot have more or fewer parameters
|
||||
// than the number required for the corresponding operator, as
|
||||
// described in the rest of this subclause.
|
||||
unsigned NumParams = FnDecl->getNumParams() + (MethodDecl? 1 : 0);
|
||||
unsigned NumParams = FnDecl->getNumParams()
|
||||
+ (isa<CXXMethodDecl>(FnDecl)? 1 : 0);
|
||||
if (Op != OO_Call &&
|
||||
((NumParams == 1 && !CanBeUnaryOperator) ||
|
||||
(NumParams == 2 && !CanBeBinaryOperator) ||
|
||||
(NumParams < 1) || (NumParams > 2))) {
|
||||
// We have the wrong number of parameters.
|
||||
std::string NumParamsStr = (llvm::APSInt(32) = NumParams).toString(10);
|
||||
std::string NumParamsStr = llvm::utostr(NumParams);
|
||||
|
||||
diag::kind DK;
|
||||
|
||||
|
@ -1946,27 +1932,23 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
|
|||
assert(false && "All non-call overloaded operators are unary or binary!");
|
||||
}
|
||||
|
||||
Diag(FnDecl->getLocation(), DK,
|
||||
FnDecl->getName(), NumParamsStr,
|
||||
SourceRange(FnDecl->getLocation()));
|
||||
IsInvalid = true;
|
||||
return Diag(FnDecl->getLocation(), DK,
|
||||
FnDecl->getName(), NumParamsStr);
|
||||
}
|
||||
|
||||
// Overloaded operators cannot be variadic.
|
||||
if (FnDecl->getType()->getAsFunctionTypeProto()->isVariadic()) {
|
||||
Diag(FnDecl->getLocation(),
|
||||
diag::err_operator_overload_variadic,
|
||||
SourceRange(FnDecl->getLocation()));
|
||||
IsInvalid = true;
|
||||
// Overloaded operators other than operator() cannot be variadic.
|
||||
if (Op != OO_Call &&
|
||||
FnDecl->getType()->getAsFunctionTypeProto()->isVariadic()) {
|
||||
return Diag(FnDecl->getLocation(),
|
||||
diag::err_operator_overload_variadic,
|
||||
FnDecl->getName());
|
||||
}
|
||||
|
||||
// Some operators must be non-static member functions.
|
||||
if (MustBeMemberOperator && !MethodDecl) {
|
||||
Diag(FnDecl->getLocation(),
|
||||
diag::err_operator_overload_must_be_member,
|
||||
FnDecl->getName(),
|
||||
SourceRange(FnDecl->getLocation()));
|
||||
IsInvalid = true;
|
||||
if (MustBeMemberOperator && !isa<CXXMethodDecl>(FnDecl)) {
|
||||
return Diag(FnDecl->getLocation(),
|
||||
diag::err_operator_overload_must_be_member,
|
||||
FnDecl->getName());
|
||||
}
|
||||
|
||||
// C++ [over.inc]p1:
|
||||
|
@ -1991,12 +1973,10 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
|
|||
DK = diag::err_operator_overload_post_inc_must_be_int;
|
||||
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;
|
||||
return Diag(LastParam->getLocation(), DK,
|
||||
Context.getCanonicalType(LastParam->getType()).getAsString());
|
||||
}
|
||||
}
|
||||
|
||||
return IsInvalid;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ struct Y {
|
|||
void operator()(int x = 17) const;
|
||||
int operator[](int);
|
||||
|
||||
static int operator+(Y, Y); // expected-error{{overloaded operator 'operator+' cannot be a static member function}}
|
||||
static int operator+(Y, Y); // expected-error{{overloaded 'operator+' cannot be a static member function}}
|
||||
};
|
||||
|
||||
|
||||
|
@ -20,15 +20,15 @@ void f(X x) {
|
|||
x = operator+(x, x);
|
||||
}
|
||||
|
||||
X operator+(int, float); // expected-error{{non-member overloaded operator 'operator+' must have at least one parameter of class or enumeration type (or reference thereof)}}
|
||||
X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}}
|
||||
|
||||
X operator*(X, X = 5); // expected-error{{a parameter of an overloaded operator cannot have a default argument}}
|
||||
X operator*(X, X = 5); // expected-error{{parameter of overloaded 'operator*' cannot have a default argument}}
|
||||
|
||||
X operator/(X, X, ...); // expected-error{{overloaded operator cannot be variadic}}
|
||||
X operator/(X, X, ...); // expected-error{{overloaded 'operator/' cannot be variadic}}
|
||||
|
||||
X operator%(Y); // expected-error{{overloaded operator 'operator%' must be a binary operator (has 1 parameter)}}
|
||||
X operator%(Y); // expected-error{{overloaded 'operator%' must be a binary operator (has 1 parameter)}}
|
||||
|
||||
void operator()(Y&, int, int); // expected-error{{overloaded operator 'operator()' must be a non-static member function}}
|
||||
void operator()(Y&, int, int); // expected-error{{overloaded 'operator()' must be a non-static member function}}
|
||||
|
||||
typedef int INT;
|
||||
typedef float FLOAT;
|
||||
|
|
Loading…
Reference in New Issue