forked from OSchip/llvm-project
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:
parent
a1b02a2380
commit
3d221f2fce
|
@ -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
|
||||
|
|
|
@ -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<
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue