Add DeclarationName support for C++0x operator literals. They should now work as

function names outside of templates - they'll probably cause some damage there as
they're largely untested.

llvm-svn: 90064
This commit is contained in:
Alexis Hunt 2009-11-29 07:34:05 +00:00
parent a1b02a2380
commit 3d221f2fce
13 changed files with 95 additions and 14 deletions

View File

@ -25,6 +25,7 @@ namespace llvm {
namespace clang {
class CXXSpecialName;
class CXXOperatorIdName;
class CXXLiteralOperatorIdName;
class DeclarationNameExtra;
class IdentifierInfo;
class MultiKeywordSelector;
@ -48,6 +49,7 @@ public:
CXXDestructorName,
CXXConversionFunctionName,
CXXOperatorName,
CXXLiteralOperatorName,
CXXUsingDirective
};
@ -115,6 +117,12 @@ private:
return 0;
}
CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
if (getNameKind() == CXXLiteralOperatorName)
return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask);
return 0;
}
// Construct a declaration name from the name of a C++ constructor,
// destructor, or conversion function.
DeclarationName(CXXSpecialName *Name)
@ -131,6 +139,12 @@ private:
Ptr |= StoredDeclarationNameExtra;
}
DeclarationName(CXXLiteralOperatorIdName *Name)
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId");
Ptr |= StoredDeclarationNameExtra;
}
/// Construct a declaration name from a raw pointer.
DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { }
@ -201,7 +215,7 @@ public:
N.Ptr = reinterpret_cast<uintptr_t> (P);
return N;
}
static DeclarationName getFromOpaqueInteger(uintptr_t P) {
DeclarationName N;
N.Ptr = P;
@ -218,6 +232,10 @@ public:
/// kind of overloaded operator.
OverloadedOperatorKind getCXXOverloadedOperator() const;
/// getCXXLiteralIdentifier - If this name is the name of a literal
/// operator, retrieve the identifier associated with it.
IdentifierInfo *getCXXLiteralIdentifier() const;
/// getObjCSelector - Get the Objective-C selector stored in this
/// declaration name.
Selector getObjCSelector() const;
@ -324,6 +342,10 @@ public:
/// getCXXOperatorName - Get the name of the overloadable C++
/// operator corresponding to Op.
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
/// getCXXLiteralOperatorName - Get the name of the literal operator function
/// with II as the identifier.
DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II);
};
/// Insertion operator for diagnostics. This allows sending DeclarationName's

View File

@ -244,8 +244,6 @@ def err_operator_missing_type_specifier : Error<
"missing type specifier after 'operator'">;
def err_operator_string_not_empty : Error<
"string literal after 'operator' must be '\"\"'">;
def err_unsupported_literal_operator : Error<
"C++0x literal operator support is currently under development">;
// Classes.
def err_anon_type_definition : Error<

View File

@ -496,6 +496,7 @@ public:
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
CXXOperator##Name,
#include "clang/Basic/OperatorKinds.def"
CXXLiteralOperator,
CXXUsingDirective,
NUM_EXTRA_KINDS
};
@ -503,10 +504,10 @@ public:
/// 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, it may be also
/// name common to C++ using-directives (CXXUsingDirective), otherwise
/// it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of
/// CXXSpecialName, (for CXXConstructor, CXXDestructor, or
/// CXXConversionFunction) CXXOperatorIdName, or CXXLiteralOperatorName,
/// it may be also name common to C++ using-directives (CXXUsingDirective),
/// 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.
unsigned ExtraKindOrNumArgs;

View File

@ -50,6 +50,17 @@ public:
void *FETokenInfo;
};
/// CXXLiberalOperatorName - Contains the actual identifier that makes up the
/// name.
///
/// This identifier is stored here rather than directly in DeclarationName so as
/// to allow Objective-C selectors, which are about a million times more common,
/// to consume minimal memory.
class CXXLiteralOperatorIdName : public DeclarationNameExtra {
public:
IdentifierInfo *ID;
};
bool operator<(DeclarationName LHS, DeclarationName RHS) {
if (LHS.getNameKind() != RHS.getNameKind())
return LHS.getNameKind() < RHS.getNameKind();
@ -89,6 +100,10 @@ bool operator<(DeclarationName LHS, DeclarationName RHS) {
case DeclarationName::CXXOperatorName:
return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator();
case DeclarationName::CXXLiteralOperatorName:
return LHS.getCXXLiteralIdentifier()->getName() <
RHS.getCXXLiteralIdentifier()->getName();
case DeclarationName::CXXUsingDirective:
return false;
@ -143,6 +158,9 @@ DeclarationName::NameKind DeclarationName::getNameKind() const {
case DeclarationNameExtra::CXXConversionFunction:
return CXXConversionFunctionName;
case DeclarationNameExtra::CXXLiteralOperator:
return CXXLiteralOperatorName;
case DeclarationNameExtra::CXXUsingDirective:
return CXXUsingDirective;
@ -208,6 +226,10 @@ std::string DeclarationName::getAsString() const {
return Result;
}
case CXXLiteralOperatorName: {
return "operator \"\" " + std::string(getCXXLiteralIdentifier()->getName());
}
case CXXConversionFunctionName: {
std::string Result = "operator ";
QualType Type = getCXXNameType();
@ -242,6 +264,13 @@ OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
}
}
IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
return CXXLit->ID;
else
return 0;
}
Selector DeclarationName::getObjCSelector() const {
switch (getNameKind()) {
case ObjCZeroArgSelector:
@ -273,6 +302,9 @@ void *DeclarationName::getFETokenInfoAsVoid() const {
case CXXOperatorName:
return getAsCXXOperatorIdName()->FETokenInfo;
case CXXLiteralOperatorName:
return getCXXLiteralIdentifier()->getFETokenInfo<void>();
default:
assert(false && "Declaration name has no FETokenInfo");
}
@ -295,6 +327,10 @@ void DeclarationName::setFETokenInfo(void *T) {
getAsCXXOperatorIdName()->FETokenInfo = T;
break;
case CXXLiteralOperatorName:
getCXXLiteralIdentifier()->setFETokenInfo(T);
break;
default:
assert(false && "Declaration name has no FETokenInfo");
}
@ -390,6 +426,14 @@ DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
}
DeclarationName
DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
CXXLiteralOperatorIdName *LiteralName = new CXXLiteralOperatorIdName;
LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
LiteralName->ID = II;
return DeclarationName(LiteralName);
}
unsigned
llvm::DenseMapInfo<clang::DeclarationName>::
getHashValue(clang::DeclarationName N) {

View File

@ -455,6 +455,12 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
cast<FunctionDecl>(ND)->getNumParams());
break;
case DeclarationName::CXXLiteralOperatorName:
// Guessing based on existing ABI.
Out << "ul";
mangleSourceName(Name.getCXXLiteralIdentifier());
break;
case DeclarationName::CXXUsingDirective:
assert(false && "Can't mangle a using directive name!");
break;

View File

@ -2589,6 +2589,10 @@ PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
return Context->DeclarationNames.getCXXOperatorName(
(OverloadedOperatorKind)Record[Idx++]);
case DeclarationName::CXXLiteralOperatorName:
return Context->DeclarationNames.getCXXLiteralOperatorName(
GetIdentifierInfo(Record, Idx));
case DeclarationName::CXXUsingDirective:
return DeclarationName::getUsingDirectiveName();
}

View File

@ -2284,6 +2284,10 @@ void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
Record.push_back(Name.getCXXOverloadedOperator());
break;
case DeclarationName::CXXLiteralOperatorName:
AddIdentifierRef(Name.getCXXLiteralIdentifier(), Record);
break;
case DeclarationName::CXXUsingDirective:
// No extra data to emit
break;

View File

@ -1052,8 +1052,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
IdentifierInfo *II = Tok.getIdentifierInfo();
Result.setLiteralOperatorId(II, KeywordLoc, ConsumeToken());
Diag(KeywordLoc, diag::err_unsupported_literal_operator);
return true;
return false;
}
// Parse a conversion-function-id.

View File

@ -1767,7 +1767,8 @@ DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) {
Name.OperatorFunctionId.Operator);
case UnqualifiedId::IK_LiteralOperatorId:
assert(false && "We don't support these; Parse shouldn't have allowed propagation");
return Context.DeclarationNames.getCXXLiteralOperatorName(
Name.Identifier);
case UnqualifiedId::IK_ConversionFunctionId: {
QualType Ty = GetTypeFromParser(Name.ConversionFunctionId);

View File

@ -729,6 +729,7 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
<< Name << computeDeclContext(SS, false)
<< SS.getRange());
else if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
Name.getNameKind() == DeclarationName::CXXLiteralOperatorName ||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
return ExprError(Diag(NameLoc, diag::err_undeclared_use)
<< Name);

View File

@ -130,8 +130,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
break;
case UnqualifiedId::IK_LiteralOperatorId:
assert(false && "We don't support these; Parse shouldn't have allowed propagation");
TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier);
break;
default:
return TNK_Non_template;

View File

@ -1800,6 +1800,7 @@ TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
case DeclarationName::CXXOperatorName:
case DeclarationName::CXXLiteralOperatorName:
case DeclarationName::CXXUsingDirective:
return Name;

View File

@ -1,5 +1,5 @@
// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
void operator "" (); // expected-error {{expected identifier}}
void operator "k" foo(); // expected-error {{string literal after 'operator' must be '""'}} \
// expected-error {{C++0x literal operator support is currently under development}}
void operator "k" foo(); // expected-error {{string literal after 'operator' must be '""'}}
void operator "" tester (int);