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
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 1ff068c..3471657 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -50,6 +50,17 @@
   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 @@
               
   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 @@
     case DeclarationNameExtra::CXXConversionFunction:
       return CXXConversionFunctionName;
 
+    case DeclarationNameExtra::CXXLiteralOperator:
+      return CXXLiteralOperatorName;
+
     case DeclarationNameExtra::CXXUsingDirective:
       return CXXUsingDirective;
 
@@ -208,6 +226,10 @@
     return Result;
   }
 
+  case CXXLiteralOperatorName: {
+    return "operator \"\" " + std::string(getCXXLiteralIdentifier()->getName());
+  }
+
   case CXXConversionFunctionName: {
     std::string Result = "operator ";
     QualType Type = getCXXNameType();
@@ -242,6 +264,13 @@
   }
 }
 
+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 @@
   case CXXOperatorName:
     return getAsCXXOperatorIdName()->FETokenInfo;
 
+  case CXXLiteralOperatorName:
+    return getCXXLiteralIdentifier()->getFETokenInfo<void>();
+
   default:
     assert(false && "Declaration name has no FETokenInfo");
   }
@@ -295,6 +327,10 @@
     getAsCXXOperatorIdName()->FETokenInfo = T;
     break;
 
+  case CXXLiteralOperatorName:
+    getCXXLiteralIdentifier()->setFETokenInfo(T);
+    break;
+
   default:
     assert(false && "Declaration name has no FETokenInfo");
   }
@@ -390,6 +426,14 @@
   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 eabdbbf..d6f7808 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -455,6 +455,12 @@
                        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 ec98348..cb96bcb 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -2589,6 +2589,10 @@
     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 f919148..e79f9c9 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -2284,6 +2284,10 @@
     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 1dc5e68..52003e6 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1052,8 +1052,7 @@
 
     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 fb97f70..6121719 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1767,7 +1767,8 @@
                                               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 f3a6765..8def7d4 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -729,6 +729,7 @@
                            << 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 9dad2f6..36895d4 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -130,8 +130,8 @@
     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 4cfaf2b..e397c2b 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1800,6 +1800,7 @@
   case DeclarationName::ObjCOneArgSelector:
   case DeclarationName::ObjCMultiArgSelector:
   case DeclarationName::CXXOperatorName:
+  case DeclarationName::CXXLiteralOperatorName:
   case DeclarationName::CXXUsingDirective:
     return Name;