[cfe-commits] r152392 - in /cfe/trunk: include/clang/Basic/ include/clang/Sema/ lib/AST/ lib/Parse/ lib/Sema/ test/CXX/lex/lex.literal/lex.ext/ test/CodeGenCXX/ test/Parser/ test/SemaCXX/

Richard Smith richard-llvm at metafoo.co.uk
Fri Mar 9 00:00:36 PST 2012


Author: rsmith
Date: Fri Mar  9 02:00:36 2012
New Revision: 152392

URL: http://llvm.org/viewvc/llvm-project?rev=152392&view=rev
Log:
Support for raw and template forms of numeric user-defined literals,
and lots of tidying up.

Added:
    cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p2.cpp
    cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p3.cpp
    cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p4.cpp
    cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p5.cpp
    cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p6.cpp
    cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p7.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Lookup.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTDiagnostic.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp
    cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp
    cfe/trunk/test/SemaCXX/cxx11-user-defined-literals.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Fri Mar  9 02:00:36 2012
@@ -43,6 +43,10 @@
   "must end with ':'">;
 def err_invalid_string_udl : Error<
   "string literal with user-defined suffix cannot be used here">;
+def err_invalid_character_udl : Error<
+  "character literal with user-defined suffix cannot be used here">;
+def err_invalid_numeric_udl : Error<
+  "numeric literal with user-defined suffix cannot be used here">;
 
 // Parse && Sema
 def ext_no_declarators : ExtWarn<"declaration does not declare anything">,

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Mar  9 02:00:36 2012
@@ -2195,7 +2195,13 @@
   "address of overloaded function %0 cannot be converted to type %1">;
 def err_addr_ovl_no_qualifier : Error<
   "can't form member pointer of type %0 without '&' and class name">;
-  
+
+// C++11 Literal Operators
+def err_ovl_no_viable_literal_operator : Error<
+  "no matching literal operator for call to %0"
+  "%select{| with argument of type %2| with arguments of types %2 and %3}1"
+  "%select{| or 'const char *', and no matching literal operator template}4">;
+
 // C++ Template Declarations
 def err_template_param_shadow : Error<
   "declaration of %0 shadows template parameter">;

Modified: cfe/trunk/include/clang/Sema/Lookup.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Lookup.h?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Lookup.h (original)
+++ cfe/trunk/include/clang/Sema/Lookup.h Fri Mar  9 02:00:36 2012
@@ -550,6 +550,11 @@
       return *I++;
     }
 
+    /// Restart the iteration.
+    void restart() {
+      I = Results.begin();
+    }
+
     /// Erase the last element returned from this iterator.
     void erase() {
       Results.Decls.erase(--I);

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Mar  9 02:00:36 2012
@@ -1552,7 +1552,8 @@
   void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
                              llvm::ArrayRef<Expr *> Args,
                              OverloadCandidateSet& CandidateSet,
-                             bool SuppressUserConversions = false);
+                             bool SuppressUserConversions = false,
+                            TemplateArgumentListInfo *ExplicitTemplateArgs = 0);
   void AddMethodCandidate(DeclAccessPair FoundDecl,
                           QualType ObjectType,
                           Expr::Classification ObjectClassification,
@@ -1794,6 +1795,22 @@
     ForRedeclaration
   };
 
+  /// \brief The possible outcomes of name lookup for a literal operator.
+  enum LiteralOperatorLookupResult {
+    /// \brief The lookup resulted in an error.
+    LOLR_Error,
+    /// \brief The lookup found a single 'cooked' literal operator, which
+    /// expects a normal literal to be built and passed to it.
+    LOLR_Cooked,
+    /// \brief The lookup found a single 'raw' literal operator, which expects
+    /// a string literal containing the spelling of the literal token.
+    LOLR_Raw,
+    /// \brief The lookup found an overload set of literal operator templates,
+    /// which expect the characters of the spelling of the literal token to be
+    /// passed as a non-type template argument pack.
+    LOLR_Template
+  };
+
   SpecialMemberOverloadResult *LookupSpecialMember(CXXRecordDecl *D,
                                                    CXXSpecialMember SM,
                                                    bool ConstArg,
@@ -1857,6 +1874,10 @@
                                         unsigned ThisQuals);
   CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
 
+  LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R,
+                                                    ArrayRef<QualType> ArgTys,
+                                                    bool AllowRawAndTemplate);
+
   void ArgumentDependentLookup(DeclarationName Name, bool Operator,
                                SourceLocation Loc,
                                llvm::ArrayRef<Expr *> Args,
@@ -2545,15 +2566,16 @@
                                       const DeclarationNameInfo &NameInfo,
                                       NamedDecl *D);
 
-  ExprResult BuildLiteralOperatorCall(IdentifierInfo *UDSuffix,
-                                      SourceLocation UDSuffixLoc,
+  ExprResult BuildLiteralOperatorCall(LookupResult &R,
+                                      DeclarationNameInfo &SuffixInfo,
                                       ArrayRef<Expr*> Args,
-                                      SourceLocation LitEndLoc);
+                                      SourceLocation LitEndLoc,
+                            TemplateArgumentListInfo *ExplicitTemplateArgs = 0);
 
   ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
   ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
-  ExprResult ActOnNumericConstant(const Token &Tok);
-  ExprResult ActOnCharacterConstant(const Token &Tok);
+  ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = 0);
+  ExprResult ActOnCharacterConstant(const Token &Tok, Scope *UDLScope = 0);
   ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E);
   ExprResult ActOnParenListExpr(SourceLocation L,
                                 SourceLocation R,
@@ -2561,8 +2583,8 @@
 
   /// ActOnStringLiteral - The specified tokens were lexed as pasted string
   /// fragments (e.g. "foo" "bar" L"baz").
-  ExprResult ActOnStringLiteral(const Token *StringToks,
-                                unsigned NumStringToks);
+  ExprResult ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
+                                Scope *UDLScope = 0);
 
   ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc,
                                        SourceLocation DefaultLoc,

Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original)
+++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Fri Mar  9 02:00:36 2012
@@ -164,6 +164,8 @@
   for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) {
     QualType CompareTy =
         QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I]));
+    if (CompareTy.isNull())
+      continue;
     if (CompareTy == Ty)
       continue;  // Same types
     QualType CompareCanTy = CompareTy.getCanonicalType();

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Mar  9 02:00:36 2012
@@ -4613,7 +4613,7 @@
   } else if (Tok.getKind() == tok::numeric_constant &&
              GetLookAheadToken(1).is(tok::r_square)) {
     // [4] is very common.  Parse the numeric constant expression.
-    ExprResult ExprRes(Actions.ActOnNumericConstant(Tok));
+    ExprResult ExprRes(Actions.ActOnNumericConstant(Tok, getCurScope()));
     ConsumeToken();
 
     T.consumeClose();

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Mar  9 02:00:36 2012
@@ -700,7 +700,7 @@
     // constant: integer-constant
     // constant: floating-constant
 
-    Res = Actions.ActOnNumericConstant(Tok);
+    Res = Actions.ActOnNumericConstant(Tok, /*UDLScope*/getCurScope());
     ConsumeToken();
     break;
 
@@ -841,7 +841,7 @@
   case tok::wide_char_constant:
   case tok::utf16_char_constant:
   case tok::utf32_char_constant:
-    Res = Actions.ActOnCharacterConstant(Tok);
+    Res = Actions.ActOnCharacterConstant(Tok, /*UDLScope*/getCurScope());
     ConsumeToken();
     break;
   case tok::kw___func__:       // primary-expression: __func__ [C99 6.4.2.2]
@@ -2120,18 +2120,13 @@
   SmallVector<Token, 4> StringToks;
 
   do {
-    if (!AllowUserDefinedLiteral && Tok.hasUDSuffix()) {
-      Diag(Tok, diag::err_invalid_string_udl);
-      do ConsumeStringToken(); while (isTokenStringLiteral());
-      return ExprError();
-    }
-
     StringToks.push_back(Tok);
     ConsumeStringToken();
   } while (isTokenStringLiteral());
 
   // Pass the set of string tokens, ready for concatenation, to the actions.
-  return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size());
+  return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size(),
+                                   AllowUserDefinedLiteral ? getCurScope() : 0);
 }
 
 /// ParseGenericSelectionExpression - Parse a C11 generic-selection

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Fri Mar  9 02:00:36 2012
@@ -2042,8 +2042,6 @@
 
   case tok::string_literal:    // primary-expression: string-literal
   case tok::wide_string_literal:
-    if (Tok.hasUDSuffix())
-      return ExprError(Diag(Tok, diag::err_invalid_string_udl));
     return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
 
   case tok::char_constant:

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Mar  9 02:00:36 2012
@@ -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();

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Mar  9 02:00:36 2012
@@ -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);
+      CookedTy = Context.UnsignedLongLongTy;
+    }
+
+    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();
 
-      QualType Ty = Context.UnsignedLongLongTy;
-      Lit = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
+    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);
     }
 
-    return BuildLiteralOperatorCall(UDSuffix, UDSuffixLoc,
-                                    llvm::makeArrayRef(&Lit, 1),
-                                    Tok.getLocation());
+    llvm_unreachable("unexpected literal operator lookup result");
   }
 
   Expr *Res;

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Mar  9 02:00:36 2012
@@ -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())];
 

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Mar  9 02:00:36 2012
@@ -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();
-
-  while (F.hasNext()) {
-    FunctionDecl *D = dyn_cast<FunctionDecl>(F.next());
-    // FIXME: using-decls?
+/// 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();
+
+  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);

Added: cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p2.cpp?rev=152392&view=auto
==============================================================================
--- cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p2.cpp (added)
+++ cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p2.cpp Fri Mar  9 02:00:36 2012
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+typedef decltype(sizeof(int)) size_t;
+
+// FIXME: These diagnostics should say 'size_t' instead of 'unsigned long'
+int a = 123_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'unsigned long long' or 'const char *', and no matching literal operator template}}
+int b = 4.2_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'long double' or 'const char *', and no matching literal operator template}}
+int c = "foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char *' and 'unsigned long'}}
+int d = L"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const wchar_t *' and 'unsigned long'}}
+int e = u8"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char *' and 'unsigned long'}}
+int f = u"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char16_t *' and 'unsigned long'}}
+int g = U"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char32_t *' and 'unsigned long'}}
+int h = 'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'char'}}
+int i = L'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'wchar_t'}}
+int j = u'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'char16_t'}}
+int k = U'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'char32_t'}}

Added: cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p3.cpp?rev=152392&view=auto
==============================================================================
--- cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p3.cpp (added)
+++ cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p3.cpp Fri Mar  9 02:00:36 2012
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+int &operator "" _x1 (unsigned long long);
+int &i1 = 0x123_x1;
+
+double &operator "" _x1 (const char *);
+int &i2 = 45_x1;
+
+template<char...> char &operator "" _x1 ();
+int &i3 = 0377_x1;
+
+int &i4 = 90000000000000000000000000000000000000000000000_x1; // expected-warning {{integer constant is too large}}
+
+double &operator "" _x2 (const char *);
+double &i5 = 123123123123123123123123123123123123123123123_x2;
+
+template<char...Cs> constexpr int operator "" _x3() { return sizeof...(Cs); }
+static_assert(123456789012345678901234567890123456789012345678901234567890_x3 == 60, "");

Added: cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p4.cpp?rev=152392&view=auto
==============================================================================
--- cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p4.cpp (added)
+++ cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p4.cpp Fri Mar  9 02:00:36 2012
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+int &operator "" _x1 (long double);
+int &i1 = 0.123_x1;
+
+double &operator "" _x1 (const char *);
+int &i2 = 45._x1;
+
+template<char...> char &operator "" _x1 ();
+int &i3 = 0377e-1_x1;
+
+int &i4 = 1e1000000_x1; // expected-warning {{too large for type 'long double'}}
+
+double &operator "" _x2 (const char *);
+double &i5 = 1e1000000_x2;
+
+template<char...Cs> constexpr int operator "" _x3() { return sizeof...(Cs); }
+static_assert(1e1000000_x3 == 9, "");

Added: cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p5.cpp?rev=152392&view=auto
==============================================================================
--- cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p5.cpp (added)
+++ cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p5.cpp Fri Mar  9 02:00:36 2012
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+using size_t = decltype(sizeof(int));
+
+int &operator "" _x1 (const char *);
+double &operator "" _x1 (const char *, size_t);
+double &i1 = "foo"_x1;
+double &i2 = u8"foo"_x1;
+double &i3 = L"foo"_x1; // expected-error {{no matching literal operator}}
+
+char &operator "" _x1(const wchar_t *, size_t);
+char &i4 = L"foo"_x1; // ok
+double &i5 = R"(foo)"_x1; // ok

Added: cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p6.cpp?rev=152392&view=auto
==============================================================================
--- cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p6.cpp (added)
+++ cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p6.cpp Fri Mar  9 02:00:36 2012
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+using size_t = decltype(sizeof(int));
+
+int &operator "" _x1 (const char *);
+double &i1 = 'a'_x1; // expected-error {{no matching literal operator}}
+double &operator "" _x1 (wchar_t);
+double &i2 = L'a'_x1;
+double &i3 = 'a'_x1; // expected-error {{no matching literal operator}}
+double &i4 = operator"" _x1('a'); // ok
+
+char &operator "" _x1(char16_t);
+char &i5 = u'a'_x1; // ok
+double &i6 = L'a'_x1; // ok

Added: cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p7.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p7.cpp?rev=152392&view=auto
==============================================================================
--- cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p7.cpp (added)
+++ cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p7.cpp Fri Mar  9 02:00:36 2012
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+using size_t = decltype(sizeof(int));
+namespace std {
+  struct string {};
+}
+
+template<typename T, typename U> struct same_type;
+template<typename T> struct same_type<T, T> {};
+
+namespace std_example {
+
+long double operator "" _w(long double);
+std::string operator "" _w(const char16_t*, size_t);
+unsigned operator "" _w(const char*);
+int main() {
+  auto v1 = 1.2_w;    // calls operator "" _w(1.2L)
+  auto v2 = u"one"_w; // calls operator "" _w(u"one", 3)
+  auto v3 = 12_w;     // calls operator "" _w("12")
+  "two"_w;            // expected-error {{no matching literal operator}}
+
+  same_type<decltype(v1), long double> test1;
+  same_type<decltype(v2), std::string> test2;
+  same_type<decltype(v3), unsigned> test3;
+}
+
+}

Modified: cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp Fri Mar  9 02:00:36 2012
@@ -6,21 +6,46 @@
 S operator"" _y(wchar_t);
 S operator"" _z(unsigned long long);
 S operator"" _f(long double);
+S operator"" _r(const char *);
+template<char...Cs> S operator"" _t() { return S(); }
+
+// CHECK: @[[s_foo:.*]] = {{.*}} constant [4 x i8] c"foo\00"
+// CHECK: @[[s_bar:.*]] = {{.*}} constant [4 x i8] c"bar\00"
+// CHECK: @[[s_123:.*]] = {{.*}} constant [4 x i8] c"123\00"
+// CHECK: @[[s_4_9:.*]] = {{.*}} constant [4 x i8] c"4.9\00"
+// CHECK: @[[s_0xffffeeee:.*]] = {{.*}} constant [11 x i8] c"0xffffeeee\00"
 
 void f() {
-  // CHECK: call void @_Zli2_xPKcm({{.*}}, i8* getelementptr inbounds ([4 x i8]* @{{.*}}, i32 0, i32 0), i64 3)
-  // CHECK: call void @_Zli2_xPKcm({{.*}}, i8* getelementptr inbounds ([4 x i8]* @{{.*}}, i32 0, i32 0), i64 3)
+  // CHECK: call void @_Zli2_xPKcm({{.*}}, i8* getelementptr inbounds ([4 x i8]* @[[s_foo]], i32 0, i32 0), i64 3)
+  // CHECK: call void @_Zli2_xPKcm({{.*}}, i8* getelementptr inbounds ([4 x i8]* @[[s_bar]], i32 0, i32 0), i64 3)
   // CHECK: call void @_Zli2_yw({{.*}} 97)
   // CHECK: call void @_Zli2_zy({{.*}} 42)
   // CHECK: call void @_Zli2_fe({{.*}} x86_fp80 0xK3FFF8000000000000000)
-  // CHECK: call void @_ZN1SD1Ev({{.*}}) nounwind
-  // CHECK: call void @_ZN1SD1Ev({{.*}}) nounwind
-  // CHECK: call void @_ZN1SD1Ev({{.*}}) nounwind
-  // CHECK: call void @_ZN1SD1Ev({{.*}}) nounwind
-  // CHECK: call void @_ZN1SD1Ev({{.*}}) nounwind
+  // CHECK: call void @_ZN1SD1Ev({{.*}})
+  // CHECK: call void @_ZN1SD1Ev({{.*}})
+  // CHECK: call void @_ZN1SD1Ev({{.*}})
+  // CHECK: call void @_ZN1SD1Ev({{.*}})
+  // CHECK: call void @_ZN1SD1Ev({{.*}})
   "foo"_x, "bar"_x, L'a'_y, 42_z, 1.0_f;
+
+  // CHECK: call void @_Zli2_rPKc({{.*}}, i8* getelementptr inbounds ([4 x i8]* @[[s_123]], i32 0, i32 0))
+  // CHECK: call void @_Zli2_rPKc({{.*}}, i8* getelementptr inbounds ([4 x i8]* @[[s_4_9]], i32 0, i32 0))
+  // CHECK: call void @_Zli2_rPKc({{.*}}, i8* getelementptr inbounds ([11 x i8]* @[[s_0xffffeeee]], i32 0, i32 0))
+  // CHECK: call void @_ZN1SD1Ev({{.*}})
+  // CHECK: call void @_ZN1SD1Ev({{.*}})
+  // CHECK: call void @_ZN1SD1Ev({{.*}})
+  123_r, 4.9_r, 0xffff\
+eeee_r;
+
+  // FIXME: This mangling is insane. Maybe we should have a special case for
+  // char parameter packs?
+  // CHECK: call void @_Zli2_tIJLc48ELc120ELc49ELc50ELc51ELc52ELc53ELc54ELc55ELc56EEE1Sv({{.*}})
+  // CHECK: call void @_ZN1SD1Ev({{.*}})
+  0x12345678_t;
 }
 
+// CHECK: define {{.*}} @_Zli2_tIJLc48ELc120ELc49ELc50ELc51ELc52ELc53ELc54ELc55ELc56EEE1Sv(
+
 template<typename T> auto g(T t) -> decltype("foo"_x(t)) { return "foo"_x(t); }
 template<typename T> auto i(T t) -> decltype(operator"" _x("foo", 3)(t)) { return operator"" _x("foo", 3)(t); }
 

Modified: cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp (original)
+++ cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp Fri Mar  9 02:00:36 2012
@@ -77,21 +77,21 @@
   erk
   flux
   )x" "eep\x1f"\
-_no_such_suffix // expected-error {{'_no_such_suffix'}}
+_no_such_suffix // expected-error {{'operator "" _no_such_suffix'}}
 "and a bit more"
 "and another suffix"_no_such_suffix;
 
 char c =
   '\x14'\
-_no_such_suffix; // expected-error {{'_no_such_suffix'}}
+_no_such_suffix; // expected-error {{'operator "" _no_such_suffix'}}
 
 int &r =
 1234567\
-_no_such_suffix; // expected-error {{'_no_such_suffix'}}
+_no_such_suffix; // expected-error {{'operator "" _no_such_suffix'}}
 
 int k =
 1234567.89\
-_no_such_suffix; // expected-error {{'_no_such_suffix'}}
+_no_such_suffix; // expected-error {{'operator "" _no_such_suffix'}}
 
 // Make sure we handle more interesting ways of writing a string literal which
 // is "" in translation phase 7.

Modified: cfe/trunk/test/SemaCXX/cxx11-user-defined-literals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx11-user-defined-literals.cpp?rev=152392&r1=152391&r2=152392&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx11-user-defined-literals.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx11-user-defined-literals.cpp Fri Mar  9 02:00:36 2012
@@ -4,7 +4,7 @@
 enum class LitKind {
   Char, WideChar, Char16, Char32,
   CharStr, WideStr, Char16Str, Char32Str,
-  Integer, Floating
+  Integer, Floating, Raw, Template
 };
 constexpr LitKind operator"" _kind(char p) { return LitKind::Char; }
 constexpr LitKind operator"" _kind(wchar_t p) { return LitKind::WideChar; }
@@ -16,6 +16,8 @@
 constexpr LitKind operator"" _kind(const char32_t *p, size_t n) { return LitKind::Char32Str; }
 constexpr LitKind operator"" _kind(unsigned long long n) { return LitKind::Integer; }
 constexpr LitKind operator"" _kind(long double n) { return LitKind::Floating; }
+constexpr LitKind operator"" _kind2(const char *p) { return LitKind::Raw; }
+template<char ...Cs> constexpr LitKind operator"" _kind3() { return LitKind::Template; }
 
 static_assert('x'_kind == LitKind::Char, "");
 static_assert(L'x'_kind == LitKind::WideChar, "");
@@ -33,3 +35,94 @@
 static_assert(1._kind == LitKind::Floating, "");
 static_assert(1.e-2_kind == LitKind::Floating, "");
 static_assert(4e6_kind == LitKind::Floating, "");
+static_assert(4e6_kind2 == LitKind::Raw, "");
+static_assert(4e6_kind3 == LitKind::Template, "");
+
+constexpr const char *fractional_digits_impl(const char *p) {
+  return *p == '.' ? p + 1 : *p ? fractional_digits_impl(p + 1) : 0;
+}
+constexpr const char *operator"" _fractional_digits(const char *p) {
+  return fractional_digits_impl(p) ?: p;
+}
+constexpr bool streq(const char *p, const char *q) {
+  return *p == *q && (!*p || streq(p+1, q+1));
+}
+
+static_assert(streq(143.97_fractional_digits, "97"), "");
+static_assert(streq(0x786_fractional_digits, "0x786"), "");
+static_assert(streq(.4_fractional_digits, "4"), "");
+static_assert(streq(4._fractional_digits, ""), "");
+static_assert(streq(1e+97_fractional_digits, "1e+97"), "");
+static_assert(streq(0377_fractional_digits, "0377"), "");
+static_assert(streq(0377.5_fractional_digits, "5"), "");
+
+int operator"" _ambiguous(char); // expected-note {{candidate}}
+namespace N {
+  void *operator"" _ambiguous(char); // expected-note {{candidate}}
+}
+using namespace N;
+int k = 'x'_ambiguous; // expected-error {{ambiguous}}
+
+int operator"" _deleted(unsigned long long) = delete; // expected-note {{here}}
+int m = 42_deleted; // expected-error {{attempt to use a deleted}}
+
+namespace Using {
+  namespace M {
+    int operator"" _using(char);
+  }
+  int k1 = 'x'_using; // expected-error {{no matching literal operator for call to 'operator "" _using'}}
+
+  using M::operator "" _using;
+  int k2 = 'x'_using;
+}
+
+namespace AmbiguousRawTemplate {
+  int operator"" _ambig1(const char *); // expected-note {{candidate}}
+  template<char...> int operator"" _ambig1(); // expected-note {{candidate}}
+
+  int k1 = 123_ambig1; // expected-error {{call to 'operator "" _ambig1' is ambiguous}}
+
+  namespace Inner {
+    template<char...> int operator"" _ambig2(); // expected-note 3{{candidate}}
+  }
+  int operator"" _ambig2(const char *); // expected-note 3{{candidate}}
+  using Inner::operator"" _ambig2;
+
+  int k2 = 123_ambig2; // expected-error {{call to 'operator "" _ambig2' is ambiguous}}
+
+  namespace N {
+    using Inner::operator"" _ambig2;
+
+    int k3 = 123_ambig2; // ok
+
+    using AmbiguousRawTemplate::operator"" _ambig2;
+
+    int k4 = 123_ambig2; // expected-error {{ambiguous}}
+
+    namespace M {
+
+      template<char...> int operator"" _ambig2();
+
+      int k5 = 123_ambig2; // ok
+    }
+
+    int operator"" _ambig2(unsigned long long);
+
+    int k6 = 123_ambig2; // ok
+    int k7 = 123._ambig2; // expected-error {{ambiguous}}
+  }
+}
+
+constexpr unsigned mash(unsigned a) {
+ return 0x93ae27b5 * ((a >> 13) | a << 19);
+}
+template<typename=void> constexpr unsigned hash(unsigned a) { return a; }
+template<char C, char...Cs> constexpr unsigned hash(unsigned a) {
+ return hash<Cs...>(mash(a ^ mash(C)));
+}
+template<typename T, T v> struct constant { constexpr static T value = v; };
+template<char...Cs> constexpr unsigned operator"" _hash() {
+  return constant<unsigned, hash<Cs...>(0)>::value;
+}
+static_assert(0x1234_hash == 0x103eff5e, "");
+static_assert(hash<'0', 'x', '1', '2', '3', '4'>(0) == 0x103eff5e, "");





More information about the cfe-commits mailing list