diff options
author | Sean Hunt <rideau3@gmail.com> | 2009-11-29 07:34:05 +0000 |
---|---|---|
committer | Sean Hunt <rideau3@gmail.com> | 2009-11-29 07:34:05 +0000 |
commit | 3e518bda00d710754ca077cf9be8dd821e16a854 (patch) | |
tree | 5d16331c76efc8c38935955af19bb351d7a2dcea | |
parent | f219e7c1529fac29e34483667f740b452e5ef9cc (diff) | |
download | clang-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.h | 24 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Basic/IdentifierTable.h | 9 | ||||
-rw-r--r-- | lib/AST/DeclarationName.cpp | 44 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 6 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 1 | ||||
-rw-r--r-- | test/Parser/cxx0x-literal-operators.cpp | 4 |
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); |