diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Decl.cpp | 4 | ||||
-rw-r--r-- | lib/AST/DeclSerialization.cpp | 14 | ||||
-rw-r--r-- | lib/AST/DeclarationName.cpp | 66 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 4 | ||||
-rw-r--r-- | lib/Basic/IdentifierTable.cpp | 22 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 46 |
11 files changed, 150 insertions, 42 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index eee934bebb..194f47f96c 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -226,8 +226,8 @@ unsigned FunctionDecl::getMinRequiredArguments() const { /// getOverloadedOperator - Which C++ overloaded operator this /// function represents, if any. OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { - if (getIdentifier()) - return getIdentifier()->getOverloadedOperatorID(); + if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName) + return getDeclName().getCXXOverloadedOperator(); else return OO_None; } diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp index 5137b720c5..8a4612b674 100644 --- a/lib/AST/DeclSerialization.cpp +++ b/lib/AST/DeclSerialization.cpp @@ -147,6 +147,10 @@ void NamedDecl::EmitInRec(Serializer& S) const { case DeclarationName::CXXConversionFunctionName: Name.getCXXNameType().Emit(S); break; + + case DeclarationName::CXXOperatorName: + S.EmitInt(Name.getCXXOverloadedOperator()); + break; } } @@ -178,8 +182,16 @@ void NamedDecl::ReadInRec(Deserializer& D, ASTContext& C) { break; case DeclarationName::CXXConversionFunctionName: - Name = C.DeclarationNames.getCXXConversionFunctionName(QualType::ReadVal(D)); + Name + = C.DeclarationNames.getCXXConversionFunctionName(QualType::ReadVal(D)); break; + + case DeclarationName::CXXOperatorName: { + OverloadedOperatorKind Op + = static_cast<OverloadedOperatorKind>(D.ReadInt()); + Name = C.DeclarationNames.getCXXOperatorName(Op); + break; + } } } diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index d58016a44c..3a9e7c84e3 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -40,6 +40,15 @@ public: } }; +/// CXXOperatorIdName - Contains extra information for the name of an +/// overloaded operator in C++, such as "operator+. +class CXXOperatorIdName : public DeclarationNameExtra { +public: + /// FETokenInfo - Extra information associated with this operator + /// name that can be used by the front end. + void *FETokenInfo; +}; + bool operator<(DeclarationName LHS, DeclarationName RHS) { if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo()) if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo()) @@ -64,7 +73,7 @@ DeclarationName::DeclarationName(Selector Sel) { default: Ptr = Sel.InfoPtr & ~Selector::ArgFlags; - Ptr |= StoredObjCMultiArgSelectorOrCXXName; + Ptr |= StoredDeclarationNameExtra; break; } } @@ -75,7 +84,7 @@ DeclarationName::NameKind DeclarationName::getNameKind() const { case StoredObjCZeroArgSelector: return ObjCZeroArgSelector; case StoredObjCOneArgSelector: return ObjCOneArgSelector; - case StoredObjCMultiArgSelectorOrCXXName: + case StoredDeclarationNameExtra: switch (getExtra()->ExtraKindOrNumArgs) { case DeclarationNameExtra::CXXConstructor: return CXXConstructorName; @@ -87,6 +96,11 @@ DeclarationName::NameKind DeclarationName::getNameKind() const { return CXXConversionFunctionName; default: + // Check if we have one of the CXXOperator* enumeration values. + if (getExtra()->ExtraKindOrNumArgs < + DeclarationNameExtra::NUM_EXTRA_KINDS) + return CXXOperatorName; + return ObjCMultiArgSelector; } break; @@ -125,6 +139,23 @@ std::string DeclarationName::getAsString() const { return Result; } + case CXXOperatorName: { + static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = { + 0, +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + Spelling, +#include "clang/Basic/OperatorKinds.def" + }; + const char *OpName = OperatorNames[getCXXOverloadedOperator()]; + assert(OpName && "not an overloaded operator"); + + std::string Result = "operator"; + if (OpName[0] >= 'a' && OpName[0] <= 'z') + Result += ' '; + Result += OpName; + return Result; + } + case CXXConversionFunctionName: { std::string Result = "operator "; QualType Type = getCXXNameType(); @@ -147,6 +178,16 @@ QualType DeclarationName::getCXXNameType() const { return QualType(); } +OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const { + if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) { + unsigned value + = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction; + return static_cast<OverloadedOperatorKind>(value); + } else { + return OO_None; + } +} + Selector DeclarationName::getObjCSelector() const { switch (getNameKind()) { case ObjCZeroArgSelector: @@ -175,6 +216,9 @@ void *DeclarationName::getFETokenInfoAsVoid() const { case CXXConversionFunctionName: return getAsCXXSpecialName()->FETokenInfo; + case CXXOperatorName: + return getAsCXXOperatorIdName()->FETokenInfo; + default: assert(false && "Declaration name has no FETokenInfo"); } @@ -193,6 +237,10 @@ void DeclarationName::setFETokenInfo(void *T) { getAsCXXSpecialName()->FETokenInfo = T; break; + case CXXOperatorName: + getAsCXXOperatorIdName()->FETokenInfo = T; + break; + default: assert(false && "Declaration name has no FETokenInfo"); } @@ -200,10 +248,19 @@ void DeclarationName::setFETokenInfo(void *T) { DeclarationNameTable::DeclarationNameTable() { CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>; + + // Initialize the overloaded operator names. + CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS]; + for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) { + CXXOperatorNames[Op].ExtraKindOrNumArgs + = Op + DeclarationNameExtra::CXXConversionFunction; + CXXOperatorNames[Op].FETokenInfo = 0; + } } DeclarationNameTable::~DeclarationNameTable() { delete static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl); + delete [] CXXOperatorNames; } DeclarationName @@ -249,3 +306,8 @@ DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, return DeclarationName(SpecialName); } +DeclarationName +DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) { + return DeclarationName(&CXXOperatorNames[(unsigned)Op]); +} + diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 22f30f451e..1155a4b9c6 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -90,10 +90,10 @@ OverloadedOperatorKind CXXOperatorCallExpr::getOperator() const { return OO_None; if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl())) - return FDecl->getIdentifier()->getOverloadedOperatorID(); + return FDecl->getDeclName().getCXXOverloadedOperator(); else if (const OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl())) - return Ovl->getIdentifier()->getOverloadedOperatorID(); + return Ovl->getDeclName().getCXXOverloadedOperator(); else return OO_None; } diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index 38bdb7e630..1bef76688c 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -28,7 +28,6 @@ using namespace clang; IdentifierInfo::IdentifierInfo() { TokenID = tok::identifier; ObjCOrBuiltinID = 0; - OperatorID = 0; HasMacro = false; IsExtension = false; IsPoisoned = false; @@ -47,7 +46,6 @@ IdentifierTable::IdentifierTable(const LangOptions &LangOpts) // Populate the identifier table with info about keywords for the current // language. AddKeywords(LangOpts); - AddOverloadedOperators(); } // This cstor is intended to be used only for serialization. @@ -163,26 +161,6 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) { #include "clang/Basic/TokenKinds.def" } -/// addOperatorPrefix - Add the prefix "operator" (possible with a -/// space after it) to the given operator symbol, and return the -/// result. -static std::string addOperatorPrefix(const char* Symbol) { - std::string result = "operator"; - if (Symbol[0] >= 'a' && Symbol[0] <= 'z') - result += ' '; - result += Symbol; - return result; -} - -/// AddOverloadedOperators - Register the name of all C++ overloadable -/// operators ("operator+", "operator[]", etc.) -void IdentifierTable::AddOverloadedOperators() { -#define OVERLOADED_OPERATOR(Name,Spelling,Token, Unary, Binary, MemberOnly) \ - OverloadedOperators[OO_##Name] = &get(addOperatorPrefix(Spelling)); \ - OverloadedOperators[OO_##Name]->setOverloadedOperatorID(OO_##Name); -#include "clang/Basic/OperatorKinds.def" -} - tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { // We use a perfect hash function here involving the length of the keyword, // the first and third character. For preprocessor ID's there are no diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index b73ee61a86..112e2bcde7 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1460,8 +1460,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { SourceLocation OperatorLoc = Tok.getLocation(); // First try the name of an overloaded operator - if (IdentifierInfo *II = TryParseOperatorFunctionId()) { - D.SetIdentifier(II, OperatorLoc); + if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) { + D.setOverloadedOperator(Op, OperatorLoc); } else { // This must be a conversion function (C++ [class.conv.fct]). if (TypeTy *ConvType = ParseConversionFunctionId()) { diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 006c79158a..90caa859a1 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -149,9 +149,9 @@ Parser::ExprResult Parser::ParseCXXIdExpression() { case tok::kw_operator: { SourceLocation OperatorLoc = Tok.getLocation(); - if (IdentifierInfo *II = TryParseOperatorFunctionId()) { - return Actions.ActOnIdentifierExpr(CurScope, OperatorLoc, *II, - Tok.is(tok::l_paren), &SS); + if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) { + return Actions.ActOnOperatorFunctionIdExpr(CurScope, OperatorLoc, Op, + Tok.is(tok::l_paren), &SS); } else if (TypeTy *Type = ParseConversionFunctionId()) { return Actions.ActOnConversionFunctionExpr(CurScope, OperatorLoc, Type, Tok.is(tok::l_paren), @@ -534,7 +534,7 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { /// ^= &= |= << >> >>= <<= == != /// <= >= && || ++ -- , ->* -> /// () [] -IdentifierInfo *Parser::TryParseOperatorFunctionId() { +OverloadedOperatorKind Parser::TryParseOperatorFunctionId() { assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); OverloadedOperatorKind Op = OO_None; @@ -549,7 +549,7 @@ IdentifierInfo *Parser::TryParseOperatorFunctionId() { } else { Op = OO_New; } - return &PP.getIdentifierTable().getOverloadedOperator(Op); + return Op; case tok::kw_delete: ConsumeToken(); // 'operator' @@ -561,7 +561,7 @@ IdentifierInfo *Parser::TryParseOperatorFunctionId() { } else { Op = OO_Delete; } - return &PP.getIdentifierTable().getOverloadedOperator(Op); + return Op; #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ case tok::Token: Op = OO_##Name; break; @@ -572,21 +572,21 @@ IdentifierInfo *Parser::TryParseOperatorFunctionId() { ConsumeToken(); // 'operator' ConsumeParen(); // '(' ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')' - return &PP.getIdentifierTable().getOverloadedOperator(OO_Call); + return OO_Call; case tok::l_square: ConsumeToken(); // 'operator' ConsumeBracket(); // '[' ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' - return &PP.getIdentifierTable().getOverloadedOperator(OO_Subscript); + return OO_Subscript; default: - return 0; + return OO_None; } ConsumeToken(); // 'operator' ConsumeAnyToken(); // the operator itself - return &PP.getIdentifierTable().getOverloadedOperator(Op); + return Op; } /// ParseConversionFunctionId - Parse a C++ conversion-function-id, diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 317cd6587e..03099956b0 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -615,6 +615,11 @@ public: IdentifierInfo &II, bool HasTrailingLParen, const CXXScopeSpec *SS = 0); + virtual ExprResult ActOnOperatorFunctionIdExpr(Scope *S, + SourceLocation OperatorLoc, + OverloadedOperatorKind Op, + bool HasTrailingLParen, + const CXXScopeSpec *SS = 0); virtual ExprResult ActOnConversionFunctionExpr(Scope *S, SourceLocation OperatorLoc, TypeTy *Ty, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index fdc4aff031..5ad1429c35 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -783,6 +783,11 @@ DeclarationName Sema::GetNameForDeclarator(Declarator &D) { Ty = Context.getCanonicalType(Ty); return Context.DeclarationNames.getCXXConversionFunctionName(Ty); } + + case Declarator::DK_Operator: + assert(D.getIdentifier() == 0 && "operator names have no identifier"); + return Context.DeclarationNames.getCXXOperatorName( + D.getOverloadedOperator()); } assert(false && "Unknown name kind"); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d113d6b6db..accdc32d45 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2839,7 +2839,7 @@ Action::ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, OverloadedOperatorKind OverOp = OverOps[Opc]; // Lookup this operator. - Decl *D = LookupDecl(&PP.getIdentifierTable().getOverloadedOperator(OverOp), + Decl *D = LookupDecl(Context.DeclarationNames.getCXXOperatorName(OverOp), Decl::IDNS_Ordinary, S); // Add any overloaded operators we find to the overload set. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index e49ef27af7..f2c6c3b35b 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -70,6 +70,52 @@ Sema::ExprResult Sema::ActOnConversionFunctionExpr(Scope *S, return new DeclRefExpr(Conversion, Conversion->getType(), OperatorLoc); } +/// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator +/// name (e.g., @c operator+ ) as an expression. This is very +/// similar to ActOnIdentifierExpr, except that instead of providing +/// an identifier the parser provides the kind of overloaded +/// operator that was parsed. +Sema::ExprResult Sema::ActOnOperatorFunctionIdExpr(Scope *S, + SourceLocation OperatorLoc, + OverloadedOperatorKind Op, + bool HasTrailingLParen, + const CXXScopeSpec *SS) { + DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op); + + Decl *D; + if (SS && !SS->isEmpty()) { + DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep()); + if (DC == 0) + return true; + D = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC); + } else + D = LookupDecl(Name, Decl::IDNS_Ordinary, S); + + if (D == 0) { + // If there is no conversion function that converts to this type, + // diagnose the problem. + if (SS && !SS->isEmpty()) + return Diag(OperatorLoc, diag::err_typecheck_no_member, + Name.getAsString(), SS->getRange()); + else + return Diag(OperatorLoc, diag::err_undeclared_var_use, + Name.getAsString()); + } + + ValueDecl *VD = cast<ValueDecl>(D); + + // check if referencing a declaration with __attribute__((deprecated)). + if (VD->getAttr<DeprecatedAttr>()) + Diag(OperatorLoc, diag::warn_deprecated, Name.getAsString()); + + // Only create DeclRefExpr's for valid Decl's. + if (VD->isInvalidDecl()) + return true; + + // Create a normal DeclRefExpr. + return new DeclRefExpr(VD, VD->getType(), OperatorLoc); +} + /// ActOnCXXTypeidOfType - Parse typeid( type-id ). Action::ExprResult Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, |