Support for raw and template forms of numeric user-defined literals,
and lots of tidying up.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152392 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 221cc6e..4d7310a 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -9306,9 +9306,15 @@
 
   bool Valid = false;
 
+  // This might be the definition of a literal operator template.
+  FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate();
+  // This might be a specialization of a literal operator template.
+  if (!TpDecl)
+    TpDecl = FnDecl->getPrimaryTemplate();
+
   // template <char...> type operator "" name() is the only valid template
   // signature, and the only valid signature with no parameters.
-  if (FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate()) {
+  if (TpDecl) {
     if (FnDecl->param_size() == 0) {
       // Must have only one template parameter
       TemplateParameterList *Params = TpDecl->getTemplateParameters();
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 64008e1..2adce06 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1130,6 +1130,35 @@
                                         S.getLangOptions());
 }
 
+/// BuildCookedLiteralOperatorCall - A user-defined literal was found. Look up
+/// the corresponding cooked (non-raw) literal operator, and build a call to it.
+static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
+                                                 IdentifierInfo *UDSuffix,
+                                                 SourceLocation UDSuffixLoc,
+                                                 ArrayRef<Expr*> Args,
+                                                 SourceLocation LitEndLoc) {
+  assert(Args.size() <= 2 && "too many arguments for literal operator");
+
+  QualType ArgTy[2];
+  for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) {
+    ArgTy[ArgIdx] = Args[ArgIdx]->getType();
+    if (ArgTy[ArgIdx]->isArrayType())
+      ArgTy[ArgIdx] = S.Context.getArrayDecayedType(ArgTy[ArgIdx]);
+  }
+
+  DeclarationName OpName =
+    S.Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
+  DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
+  OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
+
+  LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName);
+  if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()),
+                              /*AllowRawAndTemplate*/false) == Sema::LOLR_Error)
+    return ExprError();
+
+  return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc);
+}
+
 /// ActOnStringLiteral - The specified tokens were lexed as pasted string
 /// fragments (e.g. "foo" "bar" L"baz").  The result string has to handle string
 /// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
@@ -1137,7 +1166,8 @@
 /// string.
 ///
 ExprResult
-Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
+Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
+                         Scope *UDLScope) {
   assert(NumStringToks && "Must have at least one string!");
 
   StringLiteralParser Literal(StringToks, NumStringToks, PP);
@@ -1193,6 +1223,10 @@
     getUDSuffixLoc(*this, StringTokLocs[Literal.getUDSuffixToken()],
                    Literal.getUDSuffixOffset());
 
+  // Make sure we're allowed user-defined literals here.
+  if (!UDLScope)
+    return ExprError(Diag(UDSuffixLoc, diag::err_invalid_string_udl));
+
   // C++11 [lex.ext]p5: The literal L is treated as a call of the form
   //   operator "" X (str, len)
   QualType SizeType = Context.getSizeType();
@@ -1200,8 +1234,8 @@
   IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
                                                   StringTokLocs[0]);
   Expr *Args[] = { Lit, LenArg };
-  return BuildLiteralOperatorCall(UDSuffix, UDSuffixLoc, Args,
-                                  StringTokLocs.back());
+  return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc,
+                                        Args, StringTokLocs.back());
 }
 
 ExprResult
@@ -2381,7 +2415,7 @@
   return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
 }
 
-ExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
+ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
   SmallString<16> CharBuffer;
   bool Invalid = false;
   StringRef ThisTok = PP.getSpelling(Tok, CharBuffer, &Invalid);
@@ -2424,11 +2458,15 @@
   SourceLocation UDSuffixLoc =
     getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
 
+  // Make sure we're allowed user-defined literals here.
+  if (!UDLScope)
+    return ExprError(Diag(UDSuffixLoc, diag::err_invalid_character_udl));
+
   // C++11 [lex.ext]p6: The literal L is treated as a call of the form
   //   operator "" X (ch)
-  return BuildLiteralOperatorCall(UDSuffix, UDSuffixLoc,
-                                  llvm::makeArrayRef(&Lit, 1),
-                                  Tok.getLocation());
+  return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc,
+                                        llvm::makeArrayRef(&Lit, 1),
+                                        Tok.getLocation());
 }
 
 ExprResult Sema::ActOnIntegerConstant(SourceLocation Loc, uint64_t Val) {
@@ -2469,9 +2507,9 @@
   return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc);
 }
 
-ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
+ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
   // Fast path for a single digit (which is quite common).  A single digit
-  // cannot have a trigraph, escaped newline, radix prefix, or type suffix.
+  // cannot have a trigraph, escaped newline, radix prefix, or suffix.
   if (Tok.getLength() == 1) {
     const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok);
     return ActOnIntegerConstant(Tok.getLocation(), Val-'0');
@@ -2499,32 +2537,88 @@
     SourceLocation UDSuffixLoc =
       getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
 
-    // FIXME: Perform literal operator lookup now, and build a raw literal if
-    // there is no usable operator.
+    // Make sure we're allowed user-defined literals here.
+    if (!UDLScope)
+      return ExprError(Diag(UDSuffixLoc, diag::err_invalid_numeric_udl));
 
-    QualType Ty;
-    Expr *Lit;
+    QualType CookedTy;
     if (Literal.isFloatingLiteral()) {
       // C++11 [lex.ext]p4: If S contains a literal operator with parameter type
       // long double, the literal is treated as a call of the form
       //   operator "" X (f L)
-      Lit = BuildFloatingLiteral(*this, Literal, Context.LongDoubleTy,
-                                 Tok.getLocation());
+      CookedTy = Context.LongDoubleTy;
     } else {
       // C++11 [lex.ext]p3: If S contains a literal operator with parameter type
       // unsigned long long, the literal is treated as a call of the form
       //   operator "" X (n ULL)
-      llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0);
-      if (Literal.GetIntegerValue(ResultVal))
-        Diag(Tok.getLocation(), diag::warn_integer_too_large);
-
-      QualType Ty = Context.UnsignedLongLongTy;
-      Lit = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
+      CookedTy = Context.UnsignedLongLongTy;
     }
 
-    return BuildLiteralOperatorCall(UDSuffix, UDSuffixLoc,
-                                    llvm::makeArrayRef(&Lit, 1),
-                                    Tok.getLocation());
+    DeclarationName OpName =
+      Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
+    DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
+    OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
+
+    // Perform literal operator lookup to determine if we're building a raw
+    // literal or a cooked one.
+    LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
+    switch (LookupLiteralOperator(UDLScope, R, llvm::makeArrayRef(&CookedTy, 1),
+                                  /*AllowRawAndTemplate*/true)) {
+    case LOLR_Error:
+      return ExprError();
+
+    case LOLR_Cooked: {
+      Expr *Lit;
+      if (Literal.isFloatingLiteral()) {
+        Lit = BuildFloatingLiteral(*this, Literal, CookedTy, Tok.getLocation());
+      } else {
+        llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0);
+        if (Literal.GetIntegerValue(ResultVal))
+          Diag(Tok.getLocation(), diag::warn_integer_too_large);
+        Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy,
+                                     Tok.getLocation());
+      }
+      return BuildLiteralOperatorCall(R, OpNameInfo,
+                                      llvm::makeArrayRef(&Lit, 1),
+                                      Tok.getLocation());
+    }
+
+    case LOLR_Raw: {
+      // C++11 [lit.ext]p3, p4: If S contains a raw literal operator, the
+      // literal is treated as a call of the form
+      //   operator "" X ("n")
+      SourceLocation TokLoc = Tok.getLocation();
+      unsigned Length = Literal.getUDSuffixOffset();
+      QualType StrTy = Context.getConstantArrayType(
+          Context.CharTy, llvm::APInt(32, Length + 1),
+          ArrayType::Normal, 0);
+      Expr *Lit = StringLiteral::Create(
+          Context, StringRef(ThisTokBegin, Length), StringLiteral::Ascii,
+          /*Pascal*/false, StrTy, &TokLoc, 1);
+      return BuildLiteralOperatorCall(R, OpNameInfo,
+                                      llvm::makeArrayRef(&Lit, 1), TokLoc);
+    }
+
+    case LOLR_Template:
+      // C++11 [lit.ext]p3, p4: Otherwise (S contains a literal operator
+      // template), L is treated as a call fo the form
+      //   operator "" X <'c1', 'c2', ... 'ck'>()
+      // where n is the source character sequence c1 c2 ... ck.
+      TemplateArgumentListInfo ExplicitArgs;
+      unsigned CharBits = Context.getIntWidth(Context.CharTy);
+      bool CharIsUnsigned = Context.CharTy->isUnsignedIntegerType();
+      llvm::APSInt Value(CharBits, CharIsUnsigned);
+      for (unsigned I = 0, N = Literal.getUDSuffixOffset(); I != N; ++I) {
+        Value = ThisTokBegin[I];
+        TemplateArgument Arg(Value, Context.CharTy);
+        TemplateArgumentLocInfo ArgInfo;
+        ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
+      }
+      return BuildLiteralOperatorCall(R, OpNameInfo, ArrayRef<Expr*>(),
+                                      Tok.getLocation(), &ExplicitArgs);
+    }
+
+    llvm_unreachable("unexpected literal operator lookup result");
   }
 
   Expr *Res;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 40774e1..8e950ac 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -2525,6 +2525,105 @@
                                                      false, false)->getMethod());
 }
 
+/// LookupLiteralOperator - Determine which literal operator should be used for
+/// a user-defined literal, per C++11 [lex.ext].
+///
+/// Normal overload resolution is not used to select which literal operator to
+/// call for a user-defined literal. Look up the provided literal operator name,
+/// and filter the results to the appropriate set for the given argument types.
+Sema::LiteralOperatorLookupResult
+Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
+                            ArrayRef<QualType> ArgTys,
+                            bool AllowRawAndTemplate) {
+  LookupName(R, S);
+  assert(R.getResultKind() != LookupResult::Ambiguous &&
+         "literal operator lookup can't be ambiguous");
+
+  // Filter the lookup results appropriately.
+  LookupResult::Filter F = R.makeFilter();
+
+  bool FoundTemplate = false;
+  bool FoundRaw = false;
+  bool FoundExactMatch = false;
+
+  while (F.hasNext()) {
+    Decl *D = F.next();
+    if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
+      D = USD->getTargetDecl();
+
+    bool IsTemplate = isa<FunctionTemplateDecl>(D);
+    bool IsRaw = false;
+    bool IsExactMatch = false;
+
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+      if (FD->getNumParams() == 1 &&
+          FD->getParamDecl(0)->getType()->getAs<PointerType>())
+        IsRaw = true;
+      else {
+        IsExactMatch = true;
+        for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) {
+          QualType ParamTy = FD->getParamDecl(ArgIdx)->getType();
+          if (!Context.hasSameUnqualifiedType(ArgTys[ArgIdx], ParamTy)) {
+            IsExactMatch = false;
+            break;
+          }
+        }
+      }
+    }
+
+    if (IsExactMatch) {
+      FoundExactMatch = true;
+      AllowRawAndTemplate = false;
+      if (FoundRaw || FoundTemplate) {
+        // Go through again and remove the raw and template decls we've
+        // already found.
+        F.restart();
+        FoundRaw = FoundTemplate = false;
+      }
+    } else if (AllowRawAndTemplate && (IsTemplate || IsRaw)) {
+      FoundTemplate |= IsTemplate;
+      FoundRaw |= IsRaw;
+    } else {
+      F.erase();
+    }
+  }
+
+  F.done();
+
+  // C++11 [lex.ext]p3, p4: If S contains a literal operator with a matching
+  // parameter type, that is used in preference to a raw literal operator
+  // or literal operator template.
+  if (FoundExactMatch)
+    return LOLR_Cooked;
+
+  // C++11 [lex.ext]p3, p4: S shall contain a raw literal operator or a literal
+  // operator template, but not both.
+  if (FoundRaw && FoundTemplate) {
+    Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
+    for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+      Decl *D = *I;
+      if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
+        D = USD->getTargetDecl();
+      if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
+        D = FunTmpl->getTemplatedDecl();
+      NoteOverloadCandidate(cast<FunctionDecl>(D));
+    }
+    return LOLR_Error;
+  }
+
+  if (FoundRaw)
+    return LOLR_Raw;
+
+  if (FoundTemplate)
+    return LOLR_Template;
+
+  // Didn't find anything we could use.
+  Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator)
+    << R.getLookupName() << (int)ArgTys.size() << ArgTys[0]
+    << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRawAndTemplate;
+  return LOLR_Error;
+}
+
 void ADLResult::insert(NamedDecl *New) {
   NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())];
 
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 14c773f..e74e6d5 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -5236,7 +5236,8 @@
 void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
                                  llvm::ArrayRef<Expr *> Args,
                                  OverloadCandidateSet& CandidateSet,
-                                 bool SuppressUserConversions) {
+                                 bool SuppressUserConversions,
+                               TemplateArgumentListInfo *ExplicitTemplateArgs) {
   for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
     NamedDecl *D = F.getDecl()->getUnderlyingDecl();
     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -5255,13 +5256,13 @@
           !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
         AddMethodTemplateCandidate(FunTmpl, F.getPair(),
                               cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
-                                   /*FIXME: explicit args */ 0,
+                                   ExplicitTemplateArgs,
                                    Args[0]->getType(),
                                    Args[0]->Classify(Context), Args.slice(1),
                                    CandidateSet, SuppressUserConversions);
       else
         AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
-                                     /*FIXME: explicit args */ 0, Args,
+                                     ExplicitTemplateArgs, Args,
                                      CandidateSet, SuppressUserConversions);
     }
   }
@@ -10895,66 +10896,60 @@
   return MaybeBindToTemporary(TheCall);
 }
 
-static void FilterLookupForLiteralOperator(Sema &S, LookupResult &R,
-                                           ArrayRef<Expr*> Args) {
-  LookupResult::Filter F = R.makeFilter();
+/// BuildLiteralOperatorCall - Build a UserDefinedLiteral by creating a call to
+/// a literal operator described by the provided lookup results.
+ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
+                                          DeclarationNameInfo &SuffixInfo,
+                                          ArrayRef<Expr*> Args,
+                                          SourceLocation LitEndLoc,
+                                       TemplateArgumentListInfo *TemplateArgs) {
+  SourceLocation UDSuffixLoc = SuffixInfo.getCXXLiteralOperatorNameLoc();
 
-  while (F.hasNext()) {
-    FunctionDecl *D = dyn_cast<FunctionDecl>(F.next());
-    // FIXME: using-decls?
+  OverloadCandidateSet CandidateSet(UDSuffixLoc);
+  AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true,
+                        TemplateArgs);
 
-    if (!D || D->getNumParams() != Args.size()) {
-      F.erase();
-    } else {
-      // The literal operator's parameter types must exactly match the decayed
-      // argument types.
-      for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) {
-        QualType ArgTy = Args[ArgIdx]->getType();
-        QualType ParamTy = D->getParamDecl(ArgIdx)->getType();
-        if (ArgTy->isArrayType())
-          ArgTy = S.Context.getArrayDecayedType(ArgTy);
-        if (!S.Context.hasSameUnqualifiedType(ArgTy, ParamTy)) {
-          F.erase();
-          break;
-        }
-      }
-    }
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  // FIXME: Reject default arguments in literal operator definitions. We're not
+  // supposed to treat this as ambiguous:
+  //
+  //   int operator"" _x(const char *p);
+  //   int operator"" _x(const char *p, size_t n = 0);
+  //   int k = 123_x;
+
+  // Perform overload resolution. This will usually be trivial, but might need
+  // to perform substitutions for a literal operator template.
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(*this, UDSuffixLoc, Best)) {
+  case OR_Success:
+  case OR_Deleted:
+    break;
+
+  case OR_No_Viable_Function:
+    Diag(UDSuffixLoc, diag::err_ovl_no_viable_function_in_call)
+      << R.getLookupName();
+    CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
+    return ExprError();
+
+  case OR_Ambiguous:
+    Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
+    CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args);
+    return ExprError();
   }
 
-  F.done();
-}
+  FunctionDecl *FD = Best->Function;
+  MarkFunctionReferenced(UDSuffixLoc, FD);
+  DiagnoseUseOfDecl(Best->FoundDecl, UDSuffixLoc);
 
-/// BuildLiteralOperatorCall - A user-defined literal was found. Look up the
-/// corresponding literal operator, and build a call to it.
-/// FIXME: Support for raw literal operators and literal operator templates.
-ExprResult
-Sema::BuildLiteralOperatorCall(IdentifierInfo *UDSuffix,
-                               SourceLocation UDSuffixLoc,
-                               ArrayRef<Expr*> Args, SourceLocation LitEndLoc) {
-  DeclarationName OpName =
-    Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
-  DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
-  OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
-
-  LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
-  LookupName(R, /*FIXME*/CurScope);
-  assert(R.getResultKind() != LookupResult::Ambiguous &&
-         "literal operator lookup can't be ambiguous");
-
-  // Filter the lookup results appropriately.
-  FilterLookupForLiteralOperator(*this, R, Args);
-
-  // FIXME: For literal operator templates, we need to perform overload
-  // resolution to deal with SFINAE.
-  FunctionDecl *FD = R.getAsSingle<FunctionDecl>();
-  if (!FD || FD->getNumParams() != Args.size())
-    return ExprError(
-        Diag(UDSuffixLoc, diag::err_ovl_no_viable_oper) << UDSuffix->getName());
-  bool HadMultipleCandidates = false;
+  ExprResult Fn = CreateFunctionRefExpr(*this, FD, HadMultipleCandidates,
+                                        SuffixInfo.getLoc(),
+                                        SuffixInfo.getInfo());
+  if (Fn.isInvalid())
+    return true;
 
   // Check the argument types. This should almost always be a no-op, except
   // that array-to-pointer decay is applied to string literals.
-  assert(Args.size() <= 2 && "too many arguments for literal operator");
   Expr *ConvArgs[2];
   for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) {
     ExprResult InputInit = PerformCopyInitialization(
@@ -10965,26 +10960,10 @@
     ConvArgs[ArgIdx] = InputInit.take();
   }
 
-  MarkFunctionReferenced(UDSuffixLoc, FD);
-  DiagnoseUseOfDecl(FD, UDSuffixLoc);
-
-  ExprResult Fn = CreateFunctionRefExpr(*this, FD, HadMultipleCandidates,
-                                        OpNameInfo.getLoc(),
-                                        OpNameInfo.getInfo());
-  if (Fn.isInvalid())
-    return true;
-
   QualType ResultTy = FD->getResultType();
   ExprValueKind VK = Expr::getValueKindForType(ResultTy);
   ResultTy = ResultTy.getNonLValueExprType(Context);
 
-  // FIXME: A literal operator call never uses default arguments.
-  // But is this ambiguous?
-  //   void operator"" _x(const char *p);
-  //   void operator"" _x(const char *p, size_t n = 0);
-  //   123_x
-  // g++ says no, but bizarrely rejects it if the default argument is omitted.
-
   UserDefinedLiteral *UDL =
     new (Context) UserDefinedLiteral(Context, Fn.take(), ConvArgs, Args.size(),
                                      ResultTy, VK, LitEndLoc, UDSuffixLoc);