aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Decl.cpp4
-rw-r--r--lib/AST/DeclSerialization.cpp14
-rw-r--r--lib/AST/DeclarationName.cpp66
-rw-r--r--lib/AST/ExprCXX.cpp4
-rw-r--r--lib/Basic/IdentifierTable.cpp22
-rw-r--r--lib/Parse/ParseDecl.cpp4
-rw-r--r--lib/Parse/ParseExprCXX.cpp20
-rw-r--r--lib/Sema/Sema.h5
-rw-r--r--lib/Sema/SemaDecl.cpp5
-rw-r--r--lib/Sema/SemaExpr.cpp2
-rw-r--r--lib/Sema/SemaExprCXX.cpp46
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,