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/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;