[cfe-commits] r152211 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/Analysis/ lib/CodeGen/ lib/Sema/ lib/Serialization/ lib/StaticAnalyzer/Core/ test/CXX/lex/lex.literal/lex.ext/ test/CodeGenCXX/ test/PCH/ test/Parser/ test/SemaCXX/ tools/libclang/

Richard Smith richard-llvm at metafoo.co.uk
Wed Mar 7 00:35:17 PST 2012


Author: rsmith
Date: Wed Mar  7 02:35:16 2012
New Revision: 152211

URL: http://llvm.org/viewvc/llvm-project?rev=152211&view=rev
Log:
AST representation for user-defined literals, plus just enough of semantic
analysis to make the AST representation testable. They are represented by a
new UserDefinedLiteral AST node, which is a sugared CallExpr. All semantic
properties, including full CodeGen support, are achieved for free by this
representation.

UserDefinedLiterals can never be dependent, so no custom instantiation
behavior is required. They are mangled as if they were direct calls to the
underlying literal operator. This matches g++'s apparent behavior (but not its
actual mangling, which is broken for literal-operator-ids).

User-defined *string* literals are now fully-operational, but the semantic
analysis is quite hacky and needs more work. No other forms of user-defined
literal are created yet, but the AST support for them is present.

This patch committed after midnight because we had already hit the quota for
new kinds of literal yesterday.

Added:
    cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp
    cfe/trunk/test/PCH/cxx11-user-defined-literals.cpp
    cfe/trunk/test/SemaCXX/cxx11-ast-print.cpp
Modified:
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/StmtNodes.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/ExprClassification.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p10.cpp
    cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p8.cpp
    cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p9.cpp
    cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp
    cfe/trunk/tools/libclang/CXCursor.cpp

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Mar  7 02:35:16 2012
@@ -324,6 +324,67 @@
   static bool classof(const CXXConstCastExpr *) { return true; }
 };
 
+/// UserDefinedLiteral - A call to a literal operator (C++11 [over.literal])
+/// written as a user-defined literal (C++11 [lit.ext]).
+///
+/// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this
+/// is semantically equivalent to a normal call, this AST node provides better
+/// information about the syntactic representation of the literal.
+///
+/// Since literal operators are never found by ADL and can only be declared at
+/// namespace scope, a user-defined literal is never dependent.
+class UserDefinedLiteral : public CallExpr {
+  /// \brief The location of a ud-suffix within the literal.
+  SourceLocation UDSuffixLoc;
+
+public:
+  UserDefinedLiteral(ASTContext &C, Expr *Fn, Expr **Args, unsigned NumArgs,
+                     QualType T, ExprValueKind VK, SourceLocation LitEndLoc,
+                     SourceLocation SuffixLoc)
+    : CallExpr(C, UserDefinedLiteralClass, Fn, 0, Args, NumArgs, T, VK,
+               LitEndLoc), UDSuffixLoc(SuffixLoc) {}
+  explicit UserDefinedLiteral(ASTContext &C, EmptyShell Empty)
+    : CallExpr(C, UserDefinedLiteralClass, Empty) {}
+
+  /// The kind of literal operator which is invoked.
+  enum LiteralOperatorKind {
+    LOK_Raw,      ///< Raw form: operator "" X (const char *)
+    LOK_Template, ///< Raw form: operator "" X<cs...> ()
+    LOK_Integer,  ///< operator "" X (unsigned long long)
+    LOK_Floating, ///< operator "" X (long double)
+    LOK_String,   ///< operator "" X (const CharT *, size_t)
+    LOK_Character ///< operator "" X (CharT)
+  };
+
+  /// getLiteralOperatorKind - Returns the kind of literal operator invocation
+  /// which this expression represents.
+  LiteralOperatorKind getLiteralOperatorKind() const;
+
+  /// getCookedLiteral - If this is not a raw user-defined literal, get the
+  /// underlying cooked literal (representing the literal with the suffix
+  /// removed).
+  Expr *getCookedLiteral();
+  const Expr *getCookedLiteral() const {
+    return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral();
+  }
+
+  /// getUDSuffixLoc - Returns the location of a ud-suffix in the expression.
+  /// For a string literal, there may be multiple identical suffixes. This
+  /// returns the first.
+  SourceLocation getUDSuffixLoc() const { return getRParenLoc(); }
+
+  /// getUDSuffix - Returns the ud-suffix specified for this literal.
+  const IdentifierInfo *getUDSuffix() const;
+
+  static bool classof(const Stmt *S) {
+    return S->getStmtClass() == UserDefinedLiteralClass;
+  }
+  static bool classof(const UserDefinedLiteral *) { return true; }
+
+  friend class ASTStmtReader;
+  friend class ASTStmtWriter;
+};
+
 /// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal.
 ///
 class CXXBoolLiteralExpr : public Expr {

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed Mar  7 02:35:16 2012
@@ -2037,6 +2037,7 @@
 })
 DEF_TRAVERSE_STMT(CXXThisExpr, { })
 DEF_TRAVERSE_STMT(CXXThrowExpr, { })
+DEF_TRAVERSE_STMT(UserDefinedLiteral, { })
 DEF_TRAVERSE_STMT(DesignatedInitExpr, { })
 DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
 DEF_TRAVERSE_STMT(GNUNullExpr, { })

Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Wed Mar  7 02:35:16 2012
@@ -98,6 +98,7 @@
 def CXXConstCastExpr : DStmt<CXXNamedCastExpr>;
 def CXXFunctionalCastExpr : DStmt<ExplicitCastExpr>;
 def CXXTypeidExpr : DStmt<Expr>;
+def UserDefinedLiteral : DStmt<CallExpr>;
 def CXXBoolLiteralExpr : DStmt<Expr>;
 def CXXNullPtrLiteralExpr : DStmt<Expr>;
 def CXXThisExpr : DStmt<Expr>;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Mar  7 02:35:16 2012
@@ -2545,6 +2545,11 @@
                                       const DeclarationNameInfo &NameInfo,
                                       NamedDecl *D);
 
+  ExprResult BuildLiteralOperatorCall(IdentifierInfo *UDSuffix,
+                                      SourceLocation UDSuffixLoc,
+                                      ArrayRef<Expr*> Args,
+                                      SourceLocation LitEndLoc);
+
   ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
   ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
   ExprResult ActOnNumericConstant(const Token &Tok);

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Wed Mar  7 02:35:16 2012
@@ -1136,6 +1136,8 @@
       EXPR_CXX_CONST_CAST,
       /// \brief A CXXFunctionalCastExpr record.
       EXPR_CXX_FUNCTIONAL_CAST,
+      /// \brief A UserDefinedLiteral record.
+      EXPR_USER_DEFINED_LITERAL,
       /// \brief A CXXBoolLiteralExpr record.
       EXPR_CXX_BOOL_LITERAL,
       EXPR_CXX_NULL_PTR_LITERAL,  // CXXNullPtrLiteralExpr

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed Mar  7 02:35:16 2012
@@ -1681,7 +1681,8 @@
     // Fallthrough for generic call handling.
   }
   case CallExprClass:
-  case CXXMemberCallExprClass: {
+  case CXXMemberCallExprClass:
+  case UserDefinedLiteralClass: {
     // If this is a direct call, get the callee.
     const CallExpr *CE = cast<CallExpr>(this);
     if (const Decl *FD = CE->getCalleeDecl()) {
@@ -2014,7 +2015,8 @@
     //     exception-specification
   case CallExprClass:
   case CXXMemberCallExprClass:
-  case CXXOperatorCallExprClass: {
+  case CXXOperatorCallExprClass:
+  case UserDefinedLiteralClass: {
     const CallExpr *CE = cast<CallExpr>(this);
     CanThrowResult CT;
     if (isTypeDependent())

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Mar  7 02:35:16 2012
@@ -624,6 +624,39 @@
   return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
 }
 
+UserDefinedLiteral::LiteralOperatorKind
+UserDefinedLiteral::getLiteralOperatorKind() const {
+  if (getNumArgs() == 0)
+    return LOK_Template;
+  if (getNumArgs() == 2)
+    return LOK_String;
+
+  assert(getNumArgs() == 1 && "unexpected #args in literal operator call");
+  QualType ParamTy =
+    cast<FunctionDecl>(getCalleeDecl())->getParamDecl(0)->getType();
+  if (ParamTy->isPointerType())
+    return LOK_Raw;
+  if (ParamTy->isAnyCharacterType())
+    return LOK_Character;
+  if (ParamTy->isIntegerType())
+    return LOK_Integer;
+  if (ParamTy->isFloatingType())
+    return LOK_Floating;
+
+  llvm_unreachable("unknown kind of literal operator");
+}
+
+Expr *UserDefinedLiteral::getCookedLiteral() {
+#ifndef NDEBUG
+  LiteralOperatorKind LOK = getLiteralOperatorKind();
+  assert(LOK != LOK_Template && LOK != LOK_Raw && "not a cooked literal");
+#endif
+  return getArg(0);
+}
+
+const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const {
+  return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier();
+}
 
 CXXDefaultArgExpr *
 CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc, 

Modified: cfe/trunk/lib/AST/ExprClassification.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)
+++ cfe/trunk/lib/AST/ExprClassification.cpp Wed Mar  7 02:35:16 2012
@@ -269,6 +269,7 @@
   case Expr::CallExprClass:
   case Expr::CXXOperatorCallExprClass:
   case Expr::CXXMemberCallExprClass:
+  case Expr::UserDefinedLiteralClass:
   case Expr::CUDAKernelCallExprClass:
     return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType());
 

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Mar  7 02:35:16 2012
@@ -6243,6 +6243,7 @@
   case Expr::CXXTypeidExprClass:
   case Expr::CXXUuidofExprClass:
   case Expr::CXXNullPtrLiteralExprClass:
+  case Expr::UserDefinedLiteralClass:
   case Expr::CXXThisExprClass:
   case Expr::CXXThrowExprClass:
   case Expr::CXXNewExprClass:

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Mar  7 02:35:16 2012
@@ -2439,6 +2439,9 @@
                      Arity);
     break;
 
+  case Expr::UserDefinedLiteralClass:
+    // We follow g++'s approach of mangling a UDL as a call to the literal
+    // operator.
   case Expr::CXXMemberCallExprClass: // fallthrough
   case Expr::CallExprClass: {
     const CallExpr *CE = cast<CallExpr>(E);

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed Mar  7 02:35:16 2012
@@ -1222,6 +1222,31 @@
   OS << ")";
 }
 
+void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
+  switch (Node->getLiteralOperatorKind()) {
+  case UserDefinedLiteral::LOK_Raw:
+    OS << cast<StringLiteral>(Node->getArg(0))->getString();
+    break;
+  case UserDefinedLiteral::LOK_Template: {
+    DeclRefExpr *DRE = cast<DeclRefExpr>(Node->getCallee());
+    assert(DRE->hasExplicitTemplateArgs());
+    const TemplateArgumentLoc *Args = DRE->getTemplateArgs();
+    for (unsigned i = 0, e = DRE->getNumTemplateArgs(); i != e; ++i) {
+      char C = (char)Args[i].getArgument().getAsIntegral()->getZExtValue();
+      OS << C;
+    }
+    break;
+  }
+  case UserDefinedLiteral::LOK_Integer:
+  case UserDefinedLiteral::LOK_Floating:
+  case UserDefinedLiteral::LOK_String:
+  case UserDefinedLiteral::LOK_Character:
+    PrintExpr(Node->getCookedLiteral());
+    break;
+  }
+  OS << Node->getUDSuffix()->getName();
+}
+
 void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
   OS << (Node->getValue() ? "true" : "false");
 }

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Wed Mar  7 02:35:16 2012
@@ -738,6 +738,10 @@
   VisitCXXNamedCastExpr(S);
 }
 
+void StmtProfiler::VisitUserDefinedLiteral(const UserDefinedLiteral *S) {
+  VisitCallExpr(S);
+}
+
 void StmtProfiler::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
   VisitExpr(S);
   ID.AddBoolean(S->getValue());

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Wed Mar  7 02:35:16 2012
@@ -935,6 +935,7 @@
     case Stmt::CallExprClass:
     case Stmt::CXXOperatorCallExprClass:
     case Stmt::CXXMemberCallExprClass:
+    case Stmt::UserDefinedLiteralClass:
       return VisitCallExpr(cast<CallExpr>(S), asc);
 
     case Stmt::CaseStmtClass:

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Wed Mar  7 02:35:16 2012
@@ -656,6 +656,7 @@
   case Expr::CallExprClass:
   case Expr::CXXMemberCallExprClass:
   case Expr::CXXOperatorCallExprClass:
+  case Expr::UserDefinedLiteralClass:
     return EmitCallExprLValue(cast<CallExpr>(E));
   case Expr::VAArgExprClass:
     return EmitVAArgExprLValue(cast<VAArgExpr>(E));

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Mar  7 02:35:16 2012
@@ -1172,10 +1172,27 @@
                                        ArrayType::Normal, 0);
 
   // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
-  return Owned(StringLiteral::Create(Context, Literal.GetString(),
-                                     Kind, Literal.Pascal, StrTy,
-                                     &StringTokLocs[0],
-                                     StringTokLocs.size()));
+  StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(),
+                                             Kind, Literal.Pascal, StrTy,
+                                             &StringTokLocs[0],
+                                             StringTokLocs.size());
+  if (Literal.getUDSuffix().empty())
+    return Owned(Lit);
+
+  // We're building a user-defined literal.
+  IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
+  SourceLocation UDSuffixLoc = StringTokLocs[0];
+  // FIXME: = Literal.getUDSuffixLoc(getSourceManager());
+
+  // C++11 [lex.ext]p5: The literal L is treated as a call of the form
+  //   operator "" X (str, len)
+  QualType SizeType = Context.getSizeType();
+  llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
+  IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
+                                                  StringTokLocs[0]);
+  Expr *Args[] = { Lit, LenArg };
+  return BuildLiteralOperatorCall(UDSuffix, UDSuffixLoc, Args,
+                                  StringTokLocs.back());
 }
 
 ExprResult

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Mar  7 02:35:16 2012
@@ -10895,6 +10895,109 @@
   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?
+
+    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;
+        }
+      }
+    }
+  }
+
+  F.done();
+}
+
+/// 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;
+
+  // 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(
+      InitializedEntity::InitializeParameter(Context, FD->getParamDecl(ArgIdx)),
+      SourceLocation(), Args[ArgIdx]);
+    if (InputInit.isInvalid())
+      return true;
+    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);
+
+  if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD))
+    return ExprError();
+
+  if (CheckFunctionCall(FD, UDL))
+    return ExprError();
+
+  return MaybeBindToTemporary(UDL);
+}
+
 /// FixOverloadedFunctionReference - E is an expression that refers to
 /// a C++ overloaded function (possibly with some parentheses and
 /// perhaps a '&' around it). We have resolved the overloaded function

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Mar  7 02:35:16 2012
@@ -6088,6 +6088,12 @@
 
 template<typename Derived>
 ExprResult
+TreeTransform<Derived>::TransformUserDefinedLiteral(UserDefinedLiteral *E) {
+  return SemaRef.MaybeBindToTemporary(E);
+}
+
+template<typename Derived>
+ExprResult
 TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) {
   ExprResult ControllingExpr =
     getDerived().TransformExpr(E->getControllingExpr());

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Wed Mar  7 02:35:16 2012
@@ -1161,6 +1161,11 @@
   E->setRParenLoc(ReadSourceLocation(Record, Idx));
 }
 
+void ASTStmtReader::VisitUserDefinedLiteral(UserDefinedLiteral *E) {
+  VisitCallExpr(E);
+  E->UDSuffixLoc = ReadSourceLocation(Record, Idx);
+}
+
 void ASTStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
   VisitExpr(E);
   E->setValue(Record[Idx++]);
@@ -2029,6 +2034,10 @@
                        /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
       break;
 
+    case EXPR_USER_DEFINED_LITERAL:
+      S = new (Context) UserDefinedLiteral(Context, Empty);
+      break;
+
     case EXPR_CXX_BOOL_LITERAL:
       S = new (Context) CXXBoolLiteralExpr(Empty);
       break;

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Mar  7 02:35:16 2012
@@ -720,6 +720,7 @@
   RECORD(EXPR_CXX_REINTERPRET_CAST);
   RECORD(EXPR_CXX_CONST_CAST);
   RECORD(EXPR_CXX_FUNCTIONAL_CAST);
+  RECORD(EXPR_USER_DEFINED_LITERAL);
   RECORD(EXPR_CXX_BOOL_LITERAL);
   RECORD(EXPR_CXX_NULL_PTR_LITERAL);
   RECORD(EXPR_CXX_TYPEID_EXPR);

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Wed Mar  7 02:35:16 2012
@@ -1144,6 +1144,12 @@
   Code = serialization::EXPR_CXX_FUNCTIONAL_CAST;
 }
 
+void ASTStmtWriter::VisitUserDefinedLiteral(UserDefinedLiteral *E) {
+  VisitCallExpr(E);
+  Writer.AddSourceLocation(E->UDSuffixLoc, Record);
+  Code = serialization::EXPR_USER_DEFINED_LITERAL;
+}
+
 void ASTStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
   VisitExpr(E);
   Record.push_back(E->getValue());

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Mar  7 02:35:16 2012
@@ -712,7 +712,8 @@
 
     case Stmt::CallExprClass:
     case Stmt::CXXOperatorCallExprClass:
-    case Stmt::CXXMemberCallExprClass: {
+    case Stmt::CXXMemberCallExprClass:
+    case Stmt::UserDefinedLiteralClass: {
       Bldr.takeNodes(Pred);
       VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
       Bldr.addNodes(Dst);

Modified: cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p10.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p10.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p10.cpp (original)
+++ cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p10.cpp Wed Mar  7 02:35:16 2012
@@ -10,6 +10,6 @@
   // FIXME: Reject these for the right reason.
   123wibble; // expected-error {{suffix 'wibble'}}
   123.0wibble; // expected-error {{suffix 'wibble'}}
-  ""wibble; // expected-warning {{unused}}
-  R"x("hello")x"wibble; // expected-warning {{unused}}
+  ""wibble;
+  R"x("hello")x"wibble;
 }

Modified: cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p8.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p8.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p8.cpp (original)
+++ cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p8.cpp Wed Mar  7 02:35:16 2012
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c++11 -verify %s
 
-constexpr const char *operator "" _id(const char *p) { return p; }
+using size_t = decltype(sizeof(int));
+constexpr const char *operator "" _id(const char *p, size_t) { return p; }
 constexpr const char *s = "foo"_id "bar" "baz"_id "quux";
 
 constexpr bool streq(const char *p, const char *q) {
@@ -8,12 +9,10 @@
 }
 static_assert(streq(s, "foobarbazquux"), "");
 
-constexpr const char *operator "" _trim(const char *p) {
-  return *p == ' ' ? operator "" _trim(p + 1) : p;
+constexpr const char *operator "" _trim(const char *p, size_t n) {
+  return *p == ' ' ? operator "" _trim(p + 1, n - 1) : p;
 }
 constexpr const char *t = "   " " "_trim "  foo";
-// FIXME: once we implement the semantics of user-defined literals, this should
-// pass.
-static_assert(streq(s, "foo"), ""); // expected-error {{static_assert}}
+static_assert(streq(t, "foo"), "");
 
 const char *u = "foo" "bar"_id "baz" "quux"_di "corge"; // expected-error {{differing user-defined suffixes ('_id' and '_di') in string literal concatenation}}

Modified: cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p9.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p9.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p9.cpp (original)
+++ cfe/trunk/test/CXX/lex/lex.literal/lex.ext/p9.cpp Wed Mar  7 02:35:16 2012
@@ -6,9 +6,7 @@
 namespace std_example {
 
 int main() {
-  // FIXME: once we implement the semantics of literal operators, this warning
-  // should vanish.
-  L"A" "B" "C"_x; // expected-warning {{expression result unused}}
+  L"A" "B" "C"_x;
   "P"_x "Q" "R"_y; // expected-error {{differing user-defined suffixes ('_x' and '_y') in string literal concatenation}}
 }
 

Added: 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=152211&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp Wed Mar  7 02:35:16 2012
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+struct S { S(); ~S(); S(const S &); void operator()(int); };
+using size_t = decltype(sizeof(int));
+S operator"" _x(const char *, size_t);
+
+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 @_ZN1SD1Ev({{.*}}) nounwind
+  // CHECK: call void @_ZN1SD1Ev({{.*}}) nounwind
+  "foo"_x, "bar"_x;
+}
+
+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); }
+
+void h() {
+  g(42);
+  i(42);
+}
+
+// CHECK: define {{.*}} @_Z1hv()
+// CHECK:   call void @_Z1gIiEDTclclL_Zli2_xPKcmELA4_S0_ELm3EEfp_EET_(i32 42)
+// CHECK:   call void @_Z1iIiEDTclclL_Zli2_xPKcmELA4_S0_ELi3EEfp_EET_(i32 42)
+
+// CHECK: define {{.*}} @_Z1gIiEDTclclL_Zli2_xPKcmELA4_S0_ELm3EEfp_EET_(i32
+// CHECK:   call void @_Zli2_xPKcm({{.*}}, i8* getelementptr inbounds ([4 x i8]* @{{.*}}, i32 0, i32 0), i64 3)
+// CHECK:   call void @_ZN1SclEi
+// CHECK:   call void @_ZN1SD1Ev
+
+// CHECK: define {{.*}} @_Z1iIiEDTclclL_Zli2_xPKcmELA4_S0_ELi3EEfp_EET_(i32
+// CHECK:   call void @_Zli2_xPKcm({{.*}}, i8* getelementptr inbounds ([4 x i8]* @{{.*}}, i32 0, i32 0), i64 3)
+// CHECK:   call void @_ZN1SclEi
+// CHECK:   call void @_ZN1SD1Ev

Added: cfe/trunk/test/PCH/cxx11-user-defined-literals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx11-user-defined-literals.cpp?rev=152211&view=auto
==============================================================================
--- cfe/trunk/test/PCH/cxx11-user-defined-literals.cpp (added)
+++ cfe/trunk/test/PCH/cxx11-user-defined-literals.cpp Wed Mar  7 02:35:16 2012
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t
+// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t -verify %s
+
+#ifndef HEADER_INCLUDED
+
+#define HEADER_INCLUDED
+
+using size_t = decltype(sizeof(int));
+int operator"" _foo(const char *p, size_t);
+
+template<typename T> auto f(T t) -> decltype(t + ""_foo) { return 0; } // expected-note {{substitution failure}}
+
+#else
+
+int j = ""_foo;
+int k = f(0);
+int *l = f(&k);
+struct S {};
+int m = f(S()); // expected-error {{no matching}}
+
+#endif

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=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp (original)
+++ cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp Wed Mar  7 02:35:16 2012
@@ -44,11 +44,11 @@
 constexpr const char32_t operator"" _id(const char32_t *p, size_t n) { return *p; }
 
 template<int n> struct S {};
-S<"a"_id[0]> sa;
-S<L"b"_id[0]> sb;
-S<u8"c"_id[0]> sc;
-S<u"d"_id[0]> sd;
-S<U"e"_id[0]> se;
+S<"a"_id> sa;
+S<L"b"_id> sb;
+S<u8"c"_id> sc;
+S<u"d"_id> sd;
+S<U"e"_id> se;
 
 S<'w'_id> sw;
 S<L'x'_id> sx;
@@ -58,3 +58,15 @@
 void h() {
   (void)"test"_id "test" L"test";
 }
+
+enum class LitKind { CharStr, WideStr, Char16Str, Char32Str };
+constexpr LitKind operator"" _kind(const char *p, size_t n) { return LitKind::CharStr; }
+constexpr LitKind operator"" _kind(const wchar_t *p, size_t n) { return LitKind::WideStr; }
+constexpr LitKind operator"" _kind(const char16_t *p, size_t n) { return LitKind::Char16Str; }
+constexpr LitKind operator"" _kind(const char32_t *p, size_t n) { return LitKind::Char32Str; }
+
+static_assert("foo"_kind == LitKind::CharStr, "");
+static_assert(u8"foo"_kind == LitKind::CharStr, "");
+static_assert(L"foo"_kind == LitKind::WideStr, "");
+static_assert(u"foo"_kind == LitKind::Char16Str, "");
+static_assert(U"foo"_kind == LitKind::Char32Str, "");

Added: cfe/trunk/test/SemaCXX/cxx11-ast-print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx11-ast-print.cpp?rev=152211&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx11-ast-print.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx11-ast-print.cpp Wed Mar  7 02:35:16 2012
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -std=c++11 -ast-print %s | FileCheck %s
+
+// FIXME: Print the trailing-return-type properly.
+// CHECK: decltype(nullptr) operator "" _foo(const char *p, decltype(sizeof(int)));
+auto operator"" _foo(const char *p, decltype(sizeof(int))) -> decltype(nullptr);
+
+// CHECK: const char *p1 = "bar1"_foo;
+const char *p1 = "bar1"_foo;
+// CHECK: const char *p2 = "bar2"_foo;
+const char *p2 = R"x(bar2)x"_foo;
+// CHECK: const char *p3 = u8"bar3"_foo;
+const char *p3 = u8"bar3"_foo;

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=152211&r1=152210&r2=152211&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Wed Mar  7 02:35:16 2012
@@ -446,6 +446,7 @@
   case Stmt::CXXConstructExprClass:  
   case Stmt::CXXTemporaryObjectExprClass:
   case Stmt::CXXUnresolvedConstructExprClass:
+  case Stmt::UserDefinedLiteralClass:
     K = CXCursor_CallExpr;
     break;
       





More information about the cfe-commits mailing list