diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-11-17 16:14:12 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-11-17 16:14:12 +0000 |
commit | 43c7bad105f742988e7ca40564285c83bea854a5 (patch) | |
tree | 62f5c4fbbd0115f41804b3f6a213c727e72ba741 | |
parent | 1adbab67751f44147a0d259b684cf52bae142ef3 (diff) |
Some cleanups for C++ operator overloading
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59443 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 29 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 2 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 18 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 94 | ||||
-rw-r--r-- | test/SemaCXX/overloaded-operator-decl.cpp | 12 |
6 files changed, 68 insertions, 89 deletions
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 49bb9ee933..692d01d8fb 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -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'") diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 40ba2b3563..e6d3464c76 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -795,7 +795,7 @@ private: //===--------------------------------------------------------------------===// // C++ 13.5: Overloaded operators [over.oper] - IdentifierInfo *MaybeParseOperatorFunctionId(); + IdentifierInfo *TryParseOperatorFunctionId(); TypeTy *ParseConversionFunctionId(); }; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 99bebe6258..baa510485a 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -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]). diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 692e35df93..8f14ce50b8 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -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; - } - - 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, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 74d94d7132..2df6073e8b 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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; } diff --git a/test/SemaCXX/overloaded-operator-decl.cpp b/test/SemaCXX/overloaded-operator-decl.cpp index 634f3d424d..8a042f68ef 100644 --- a/test/SemaCXX/overloaded-operator-decl.cpp +++ b/test/SemaCXX/overloaded-operator-decl.cpp @@ -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; |