<p>Given
a <code>DeclarationName</code> <code>N</code>, <code>N.getNameKind()</code>
will produce a value that describes what kind of name <code>N</code>
- stores. There are 7 options (all of the names are inside
+ stores. There are 8 options (all of the names are inside
the <code>DeclarationName</code> class)</p>
<dl>
<dt>Identifier</dt>
const *</code>". Use <code>N.getCXXNameType()</code> to retrieve
the type that this conversion function converts to. This type is
always a canonical type.</dd>
+
+ <dt>CXXOperatorName</dt>
+ <dd>The name is a C++ overloaded operator name. Overloaded operators
+ are named according to their spelling, e.g.,
+ "<code>operator+</code>" or "<code>operator new
+ []</code>". Use <code>N.getCXXOverloadedOperator()</code> to
+ retrieve the overloaded operator (a value of
+ type <code>OverloadedOperatorKind</code>).</dd>
</dl>
<p><code>DeclarationName</code>s are cheap to create, copy, and
compare. They require only a single pointer's worth of storage in
- the common cases (identifiers, C++ overloaded operator names, zero-
+ the common cases (identifiers, zero-
and one-argument Objective-C selectors) and use dense, uniqued
storage for the other kinds of
names. Two <code>DeclarationName</code>s can be compared for
<p><code>DeclarationName</code> instances can be created in different
ways depending on what kind of name the instance will store. Normal
- identifiers (<code>IdentifierInfo</code> pointers), including
- overloaded operator names, and Objective-C selectors
+ identifiers (<code>IdentifierInfo</code> pointers) and Objective-C selectors
(<code>Selector</code>) can be implicitly converted
to <code>DeclarationName</code>s. Names for C++ constructors,
- destructors, and conversion functions can be retrieved from
+ destructors, conversion functions, and overloaded operators can be retrieved from
the <code>DeclarationNameTable</code>, an instance of which is
available as <code>ASTContext::DeclarationNames</code>. The member
functions <code>getCXXConstructorName</code>, <code>getCXXDestructorName</code>,
- and <code>getCXXConversionFunctionName</code>, respectively,
- return <code>DeclarationName</code> instances for the three kinds of
+ <code>getCXXConversionFunctionName</code>, and <code>getCXXOperatorName</code>, respectively,
+ return <code>DeclarationName</code> instances for the four kinds of
C++ special function names.</p>
<!-- ======================================================================= -->
namespace clang {
class CXXSpecialName; // a private class used by DeclarationName
+ class CXXOperatorIdName; // a private class used by DeclarationName
class DeclarationNameExtra; // a private class used by DeclarationName
class IdentifierInfo;
class MultiKeywordSelector; // a private class used by Selector and DeclarationName
ObjCMultiArgSelector,
CXXConstructorName,
CXXDestructorName,
- CXXConversionFunctionName
+ CXXConversionFunctionName,
+ CXXOperatorName
};
private:
StoredIdentifier = 0,
StoredObjCZeroArgSelector,
StoredObjCOneArgSelector,
- StoredObjCMultiArgSelectorOrCXXName,
+ StoredDeclarationNameExtra,
PtrMask = 0x03
};
/// on the kind of name this is, the upper bits of Ptr may have one
/// of several different meanings:
///
- /// Identifier - The name is a normal identifier, and Ptr is a
- /// normal IdentifierInfo pointer.
+ /// StoredIdentifier - The name is a normal identifier, and Ptr is
+ /// a normal IdentifierInfo pointer.
///
- /// ObjCZeroArgSelector - The name is an Objective-C selector with
- /// zero arguments, and Ptr is an IdentifierInfo pointer pointing
- /// to the selector name.
+ /// StoredObjCZeroArgSelector - The name is an Objective-C
+ /// selector with zero arguments, and Ptr is an IdentifierInfo
+ /// pointer pointing to the selector name.
///
- /// ObjCOneArgSelector - The name is an Objective-C selector with
- /// one argument, and Ptr is an IdentifierInfo pointer pointing to
- /// the selector name.
+ /// StoredObjCOneArgSelector - The name is an Objective-C selector
+ /// with one argument, and Ptr is an IdentifierInfo pointer
+ /// pointing to the selector name.
///
- /// ObjCMultiArgSelectorOrCXXName - This is either an Objective-C
- /// selector with two or more arguments or it is a C++ name. Ptr
- /// is actually a DeclarationNameExtra structure, whose first
- /// value will tell us whether this is an Objective-C selector or
- /// special C++ name.
+ /// StoredDeclarationNameExtra - Ptr is actually a pointer to a
+ /// DeclarationNameExtra structure, whose first value will tell us
+ /// whether this is an Objective-C selector, C++ operator-id name,
+ /// or special C++ name.
uintptr_t Ptr;
/// getStoredNameKind - Return the kind of object that is stored in
/// getExtra - Get the "extra" information associated with this
/// multi-argument selector or C++ special name.
DeclarationNameExtra *getExtra() const {
- assert(getStoredNameKind() == StoredObjCMultiArgSelectorOrCXXName &&
+ assert(getStoredNameKind() == StoredDeclarationNameExtra &&
"Declaration name does not store an Extra structure");
return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask);
}
return 0;
}
+ /// getAsCXXOperatorIdName
+ CXXOperatorIdName *getAsCXXOperatorIdName() const {
+ if (getNameKind() == CXXOperatorName)
+ return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
+ else
+ return 0;
+ }
+
// Construct a declaration name from the name of a C++ constructor,
// destructor, or conversion function.
DeclarationName(CXXSpecialName *Name)
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
- Ptr |= StoredObjCMultiArgSelectorOrCXXName;
+ Ptr |= StoredDeclarationNameExtra;
+ }
+
+ // Construct a declaration name from the name of a C++ overloaded
+ // operator.
+ DeclarationName(CXXOperatorIdName *Name)
+ : Ptr(reinterpret_cast<uintptr_t>(Name)) {
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId");
+ Ptr |= StoredDeclarationNameExtra;
}
// Construct a declaration name from a zero- or one-argument
DeclarationName(MultiKeywordSelector *SI)
: Ptr(reinterpret_cast<uintptr_t>(SI)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
- Ptr |= StoredObjCMultiArgSelectorOrCXXName;
+ Ptr |= StoredDeclarationNameExtra;
}
/// Construct a declaration name from a raw pointer.
/// type associated with that name.
QualType getCXXNameType() const;
+ /// getCXXOverloadedOperator - If this name is the name of an
+ /// overloadable operator in C++ (e.g., @c operator+), retrieve the
+ /// kind of overloaded operator.
+ OverloadedOperatorKind getCXXOverloadedOperator() const;
+
/// getObjCSelector - Get the Objective-C selector stored in this
/// declaration name.
Selector getObjCSelector() const;
/// getCXXConstructorName).
class DeclarationNameTable {
void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
+ CXXOperatorIdName *CXXOperatorNames; // Operator names
DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE
DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
/// function.
DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
QualType Ty);
+
+ /// getCXXOperatorName - Get the name of the overloadable C++
+ /// operator corresponding to Op.
+ DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
};
} // end namespace clang
// First NUM_OBJC_KEYWORDS values are for Objective-C, the remaining values
// are for builtins.
unsigned ObjCOrBuiltinID :10;
- unsigned OperatorID : 6; // C++ overloaded operator.
bool HasMacro : 1; // True if there is a #define for this.
bool IsExtension : 1; // True if identifier is a lang extension.
bool IsPoisoned : 1; // True if identifier is poisoned.
bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
- // 4 bits left in 32-bit word.
+ // 10 bits left in 32-bit word.
void *FETokenInfo; // Managed by the language front-end.
IdentifierInfo(const IdentifierInfo&); // NONCOPYABLE.
void operator=(const IdentifierInfo&); // NONASSIGNABLE.
&& "ID too large for field!");
}
- /// getOverloadedOperatorID - Get the C++ overloaded operator that
- /// corresponds to this identifier.
- OverloadedOperatorKind getOverloadedOperatorID() const {
- return OverloadedOperatorKind(OperatorID);
- }
- void setOverloadedOperatorID(OverloadedOperatorKind ID) {
- OperatorID = ID;
- assert(OperatorID == (unsigned)ID && "ID too large for field!");
- }
-
/// get/setExtension - Initialize information about whether or not this
/// language token is an extension. This controls extension warnings, and is
/// only valid if a custom token ID is set.
typedef llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator> HashTableTy;
HashTableTy HashTable;
- /// OverloadedOperators - Identifiers corresponding to each of the
- /// overloadable operators in C++.
- IdentifierInfo *OverloadedOperators[NUM_OVERLOADED_OPERATORS];
-
public:
/// IdentifierTable ctor - Create the identifier table, populating it with
/// info about the language keywords for the language specified by LangOpts.
return get(NameBytes, NameBytes+Name.size());
}
- /// getOverloadedOperator - Retrieve the identifier
- IdentifierInfo &getOverloadedOperator(OverloadedOperatorKind Op) {
- return *OverloadedOperators[Op];
- }
-
typedef HashTableTy::const_iterator iterator;
typedef HashTableTy::const_iterator const_iterator;
void PrintStats() const;
void AddKeywords(const LangOptions &LangOpts);
- void AddOverloadedOperators();
/// Emit - Serialize this IdentifierTable to a bitstream. This should
/// be called AFTER objects that externally reference the identifiers in the
static SelectorTable* CreateAndRegister(llvm::Deserializer& D);
};
-/// DeclarationNameExtra - Common base of the MultiKeywordSelector and
-/// CXXSpecialName classes, both of which are private classes that can
-/// be stored by the AST's DeclarationName class.
+/// DeclarationNameExtra - Common base of the MultiKeywordSelector,
+/// CXXSpecialName, and CXXOperatorIdName classes, all of which are
+/// private classes that describe different kinds of names.
class DeclarationNameExtra {
public:
/// ExtraKind - The kind of "extra" information stored in the
CXXConstructor = 0,
CXXDestructor,
CXXConversionFunction,
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ CXXOperator##Name,
+#include "clang/Basic/OperatorKinds.def"
NUM_EXTRA_KINDS
};
- /// ExtraKindOrNumArgs - Either the kind of C++ special name (if the
- /// value is one of the CXX* enumerators of ExtraKind), in which
- /// case the DeclarationNameExtra is also a CXXSpecialName, or
+ /// ExtraKindOrNumArgs - Either the kind of C++ special name or
+ /// operator-id (if the value is one of the CXX* enumerators of
+ /// ExtraKind), in which case the DeclarationNameExtra is also a
+ /// CXXSpecialName (for CXXConstructor, CXXDestructor, or
+ /// CXXConversionFunction) or CXXOperatorIdName, otherwise it is
/// NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of
/// arguments in the Objective-C selector, in which case the
/// DeclarationNameExtra is also a MultiKeywordSelector.
const CXXScopeSpec *SS = 0) {
return 0;
}
+
+ /// 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.
+ virtual ExprResult ActOnOperatorFunctionIdExpr(Scope *S,
+ SourceLocation OperatorLoc,
+ OverloadedOperatorKind Op,
+ bool HasTrailingLParen,
+ const CXXScopeSpec *SS = 0) {
+ return 0;
+ }
/// ActOnConversionFunctionExpr - Parse a C++ conversion function
- /// name (e.g., operator void const *) as an expression. This is
+ /// name (e.g., @c operator void const *) as an expression. This is
/// very similar to ActOnIdentifierExpr, except that instead of
/// providing an identifier the parser provides the type of the
/// conversion function.
DK_Normal, // A normal declarator (has an identifier).
DK_Constructor, // A C++ constructor (identifier is the class name)
DK_Destructor, // A C++ destructor (identifier is ~class name)
+ DK_Operator, // A C++ overloaded operator name
DK_Conversion // A C++ conversion function (identifier is
// "operator " then the type name)
};
/// AsmLabel - The asm label, if specified.
Action::ExprTy *AsmLabel;
- // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the
- // type associated with the constructor, destructor, or conversion
- // operator.
- Action::TypeTy *Type;
+ union {
+ // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the
+ // type associated with the constructor, destructor, or conversion
+ // operator.
+ Action::TypeTy *Type;
+
+ /// When Kind is DK_Operator, this is the actual overloaded
+ /// operator that this declarator names.
+ OverloadedOperatorKind OperatorKind;
+ };
public:
Declarator(const DeclSpec &ds, TheContext C)
}
// setConversionFunction - Set this declarator to be a C++
- // conversion function declarator.
+ // conversion function declarator (e.g., @c operator int const *).
void setConversionFunction(Action::TypeTy *Ty, SourceLocation Loc) {
Identifier = 0;
IdentifierLoc = Loc;
Type = Ty;
}
+ // setOverloadedOperator - Set this declaration to be a C++
+ // overloaded operator declarator (e.g., @c operator+).
+ void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc) {
+ IdentifierLoc = Loc;
+ Kind = DK_Operator;
+ OperatorKind = Op;
+ }
+
void AddTypeInfo(const DeclaratorChunk &TI) {
DeclTypeInfo.push_back(TI);
}
Action::TypeTy *getDeclaratorIdType() const { return Type; }
+ OverloadedOperatorKind getOverloadedOperator() const { return OperatorKind; }
+
void setInvalidType(bool flag) { InvalidType = flag; }
bool getInvalidType() const { return InvalidType; }
//===--------------------------------------------------------------------===//
// C++ 13.5: Overloaded operators [over.oper]
- IdentifierInfo *TryParseOperatorFunctionId();
+ OverloadedOperatorKind TryParseOperatorFunctionId();
TypeTy *ParseConversionFunctionId();
};
/// 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;
}
case DeclarationName::CXXConversionFunctionName:
Name.getCXXNameType().Emit(S);
break;
+
+ case DeclarationName::CXXOperatorName:
+ S.EmitInt(Name.getCXXOverloadedOperator());
+ break;
}
}
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;
+ }
}
}
}
};
+/// 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())
default:
Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
- Ptr |= StoredObjCMultiArgSelectorOrCXXName;
+ Ptr |= StoredDeclarationNameExtra;
break;
}
}
case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
case StoredObjCOneArgSelector: return ObjCOneArgSelector;
- case StoredObjCMultiArgSelectorOrCXXName:
+ case StoredDeclarationNameExtra:
switch (getExtra()->ExtraKindOrNumArgs) {
case DeclarationNameExtra::CXXConstructor:
return CXXConstructorName;
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;
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();
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:
case CXXConversionFunctionName:
return getAsCXXSpecialName()->FETokenInfo;
+ case CXXOperatorName:
+ return getAsCXXOperatorIdName()->FETokenInfo;
+
default:
assert(false && "Declaration name has no FETokenInfo");
}
getAsCXXSpecialName()->FETokenInfo = T;
break;
+ case CXXOperatorName:
+ getAsCXXOperatorIdName()->FETokenInfo = T;
+ break;
+
default:
assert(false && "Declaration name has no FETokenInfo");
}
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
return DeclarationName(SpecialName);
}
+DeclarationName
+DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
+ return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
+}
+
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;
}
IdentifierInfo::IdentifierInfo() {
TokenID = tok::identifier;
ObjCOrBuiltinID = 0;
- OperatorID = 0;
HasMacro = false;
IsExtension = false;
IsPoisoned = false;
// 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.
#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
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()) {
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),
/// ^= &= |= << >> >>= <<= == !=
/// <= >= && || ++ -- , ->* ->
/// () []
-IdentifierInfo *Parser::TryParseOperatorFunctionId() {
+OverloadedOperatorKind Parser::TryParseOperatorFunctionId() {
assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
OverloadedOperatorKind Op = OO_None;
} else {
Op = OO_New;
}
- return &PP.getIdentifierTable().getOverloadedOperator(Op);
+ return Op;
case tok::kw_delete:
ConsumeToken(); // 'operator'
} 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;
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,
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,
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");
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.
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,
x = operator+(x, x);
}
-X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}} \
- // expected-error{{previous definition is here}}
+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{{parameter of overloaded 'operator*' cannot have a default argument}}
Y operator++(Y&, INT);
X operator++(X&, FLOAT); // expected-error{{parameter of overloaded post-increment operator must have type 'int' (not 'float')}}
-int operator+; // expected-error{{redefinition of 'operator+' as different kind of symbol}}
+int operator+; // expected-error{{'operator+' cannot be the name of a variable or data member}}