]> granicus.if.org Git - clang/commitdiff
Add DeclarationName support for C++0x operator literals. They should now work as
authorSean Hunt <rideau3@gmail.com>
Sun, 29 Nov 2009 07:34:05 +0000 (07:34 +0000)
committerSean Hunt <rideau3@gmail.com>
Sun, 29 Nov 2009 07:34:05 +0000 (07:34 +0000)
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

13 files changed:
include/clang/AST/DeclarationName.h
include/clang/Basic/DiagnosticParseKinds.td
include/clang/Basic/IdentifierTable.h
lib/AST/DeclarationName.cpp
lib/CodeGen/Mangle.cpp
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Parse/ParseExprCXX.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/TreeTransform.h
test/Parser/cxx0x-literal-operators.cpp

index 0e8aad5d93df781e8e78421e3035ab90af857002..676bd2ca7336cb0f894d3271bd2825b3971b9012 100644 (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
index 7de5b20d6ee8a29c7c504e33b8924c533e26a50a..43107044720e6a986c2966534fe8a4a717957d7a 100644 (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<
index e06dfbb2cf1beec685dd2243f0b13033053aecc3..53939500e72ad5bffac8e1e10f18f43ba2994db0 100644 (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;
index 1ff068c9862c12a60e3acfc0ed1485f5c50c72a3..3471657b652374d5ff581f9279171feffcb0bfc0 100644 (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) {
index eabdbbfde9e5bbc8379c8a66b7f053d5894f84bb..d6f7808c4073d06b0f2939dd5baf01682c2705c5 100644 (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;
index ec9834894fb6730c50f4f87e3cc5a5f1b576391b..cb96bcb48aec21aa545cd7328842fc79d57fabeb 100644 (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();
   }
index f919148a7748567366e1ea9e80d85ab30c26e50d..e79f9c9dac19ce38fdbe573b8127904f2fc8d82a 100644 (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;
index 1dc5e68717e34c88eaaf0cbefd0ac0ecee48dec2..52003e6fa1b26526833583e46ab31ee2948cde35 100644 (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.
index fb97f7000f8c68a9a91fd283f001eef19c1dd720..6121719abb6ac44df61223890aeb3ab0a2f71a79 100644 (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);
index f3a6765a6a22e6510d4a07e9a83fa2f0d4dc4bf1..8def7d4efc51b1257f07272837e6616475bca858 100644 (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);
index 9dad2f63c87abf077629e15c498b50986181691b..36895d4726c5b8b84b6987020f2609f83328c3a9 100644 (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;
index 4cfaf2b79ba8caaacb49ee84a0d2f26b38301a03..e397c2b294a721bb8c2e0f5c8a6f198fe0093da2 100644 (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;
 
index 6930adbe3720291c82974b75614fb38f26fdee03..c5514601d11615e9c6109df6a02c34e9dcc18965 100644 (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);