summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hunt <rideau3@gmail.com>2009-11-29 07:34:05 +0000
committerSean Hunt <rideau3@gmail.com>2009-11-29 07:34:05 +0000
commit3e518bda00d710754ca077cf9be8dd821e16a854 (patch)
tree5d16331c76efc8c38935955af19bb351d7a2dcea
parentf219e7c1529fac29e34483667f740b452e5ef9cc (diff)
downloadclang-3e518bda00d710754ca077cf9be8dd821e16a854.tar.gz
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90064 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/DeclarationName.h24
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td2
-rw-r--r--include/clang/Basic/IdentifierTable.h9
-rw-r--r--lib/AST/DeclarationName.cpp44
-rw-r--r--lib/CodeGen/Mangle.cpp6
-rw-r--r--lib/Frontend/PCHReader.cpp4
-rw-r--r--lib/Frontend/PCHWriter.cpp4
-rw-r--r--lib/Parse/ParseExprCXX.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp3
-rw-r--r--lib/Sema/SemaExpr.cpp1
-rw-r--r--lib/Sema/SemaTemplate.cpp4
-rw-r--r--lib/Sema/TreeTransform.h1
-rw-r--r--test/Parser/cxx0x-literal-operators.cpp4
13 files changed, 95 insertions, 14 deletions
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 0e8aad5d93..676bd2ca73 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -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
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 7de5b20d6e..4310704472 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -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<
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index e06dfbb2cf..53939500e7 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -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;
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 1ff068c986..3471657b65 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -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) {
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index eabdbbfde9..d6f7808c40 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -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;
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index ec9834894f..cb96bcb48a 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -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();
}
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index f919148a77..e79f9c9dac 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -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;
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 1dc5e68717..52003e6fa1 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -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.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index fb97f7000f..6121719abb 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f3a6765a6a..8def7d4efc 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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);
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 9dad2f63c8..36895d4726 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -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;
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 4cfaf2b79b..e397c2b294 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -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;
diff --git a/test/Parser/cxx0x-literal-operators.cpp b/test/Parser/cxx0x-literal-operators.cpp
index 6930adbe37..c5514601d1 100644
--- a/test/Parser/cxx0x-literal-operators.cpp
+++ b/test/Parser/cxx0x-literal-operators.cpp
@@ -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);