[cfe-commits] r152277 - in /cfe/trunk: include/clang/Lex/LiteralSupport.h lib/Lex/LiteralSupport.cpp lib/Sema/SemaExpr.cpp test/CodeGenCXX/cxx11-user-defined-literal.cpp test/Parser/cxx11-user-defined-literals.cpp

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


Author: rsmith
Date: Wed Mar  7 19:34:56 2012
New Revision: 152277

URL: http://llvm.org/viewvc/llvm-project?rev=152277&view=rev
Log:
User-defined literal support for character literals.

Modified:
    cfe/trunk/include/clang/Lex/LiteralSupport.h
    cfe/trunk/lib/Lex/LiteralSupport.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp
    cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp

Modified: cfe/trunk/include/clang/Lex/LiteralSupport.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/LiteralSupport.h?rev=152277&r1=152276&r2=152277&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/LiteralSupport.h (original)
+++ cfe/trunk/include/clang/Lex/LiteralSupport.h Wed Mar  7 19:34:56 2012
@@ -129,6 +129,7 @@
   bool IsMultiChar;
   bool HadError;
   SmallString<32> UDSuffixBuf;
+  unsigned UDSuffixOffset;
 public:
   CharLiteralParser(const char *begin, const char *end,
                     SourceLocation Loc, Preprocessor &PP,
@@ -142,6 +143,10 @@
   bool isMultiChar() const { return IsMultiChar; }
   uint64_t getValue() const { return Value; }
   StringRef getUDSuffix() const { return UDSuffixBuf; }
+  unsigned getUDSuffixOffset() const {
+    assert(!UDSuffixBuf.empty() && "no ud-suffix");
+    return UDSuffixOffset;
+  }
 };
 
 /// StringLiteralParser - This decodes string escape characters and performs
@@ -160,6 +165,8 @@
   SmallString<512> ResultBuf;
   char *ResultPtr; // cursor
   SmallString<32> UDSuffixBuf;
+  unsigned UDSuffixToken;
+  unsigned UDSuffixOffset;
 public:
   StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
                       Preprocessor &PP, bool Complain = true);
@@ -201,6 +208,17 @@
 
   StringRef getUDSuffix() const { return UDSuffixBuf; }
 
+  /// Get the index of a token containing a ud-suffix.
+  unsigned getUDSuffixToken() const {
+    assert(!UDSuffixBuf.empty() && "no ud-suffix");
+    return UDSuffixToken;
+  }
+  /// Get the spelling offset of the first byte of the ud-suffix.
+  unsigned getUDSuffixOffset() const {
+    assert(!UDSuffixBuf.empty() && "no ud-suffix");
+    return UDSuffixOffset;
+  }
+
 private:
   void init(const Token *StringToks, unsigned NumStringToks);
   bool CopyStringFragment(StringRef Fragment);

Modified: cfe/trunk/lib/Lex/LiteralSupport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/LiteralSupport.cpp?rev=152277&r1=152276&r2=152277&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/LiteralSupport.cpp (original)
+++ cfe/trunk/lib/Lex/LiteralSupport.cpp Wed Mar  7 19:34:56 2012
@@ -791,6 +791,7 @@
       --end;
     } while (end[-1] != '\'');
     UDSuffixBuf.assign(end, UDSuffixEnd);
+    UDSuffixOffset = end - begin + 1;
   }
 
   // Trim the ending quote.
@@ -1113,6 +1114,8 @@
 
       if (UDSuffixBuf.empty()) {
         UDSuffixBuf.assign(UDSuffix);
+        UDSuffixToken = i;
+        UDSuffixOffset = ThisTokEnd - ThisTokBuf;
         UDSuffixTokLoc = StringToks[i].getLocation();
       } else if (!UDSuffixBuf.equals(UDSuffix)) {
         // C++11 [lex.ext]p8: At the end of phase 6, if a string literal is the

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=152277&r1=152276&r2=152277&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Mar  7 19:34:56 2012
@@ -1122,6 +1122,14 @@
                  ResultIndex));
 }
 
+/// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the
+/// location of the token and the offset of the ud-suffix within it.
+static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc,
+                                     unsigned Offset) {
+  return Lexer::AdvanceToTokenCharacter(TokLoc, Offset, S.getSourceManager(),
+                                        S.getLangOptions());
+}
+
 /// 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
@@ -1181,8 +1189,9 @@
 
   // We're building a user-defined literal.
   IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
-  SourceLocation UDSuffixLoc = StringTokLocs[0];
-  // FIXME: = Literal.getUDSuffixLoc(getSourceManager());
+  SourceLocation UDSuffixLoc =
+    getUDSuffixLoc(*this, StringTokLocs[Literal.getUDSuffixToken()],
+                   Literal.getUDSuffixOffset());
 
   // C++11 [lex.ext]p5: The literal L is treated as a call of the form
   //   operator "" X (str, len)
@@ -2404,8 +2413,22 @@
   else if (Literal.isUTF32())
     Kind = CharacterLiteral::UTF32;
 
-  return Owned(new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty,
-                                              Tok.getLocation()));
+  Expr *Lit = new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty,
+                                             Tok.getLocation());
+
+  if (Literal.getUDSuffix().empty())
+    return Owned(Lit);
+
+  // We're building a user-defined literal.
+  IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
+  SourceLocation UDSuffixLoc =
+    getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
+
+  // 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());
 }
 
 ExprResult Sema::ActOnIntegerConstant(SourceLocation Loc, uint64_t Val) {

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=152277&r1=152276&r2=152277&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx11-user-defined-literal.cpp Wed Mar  7 19:34:56 2012
@@ -3,13 +3,16 @@
 struct S { S(); ~S(); S(const S &); void operator()(int); };
 using size_t = decltype(sizeof(int));
 S operator"" _x(const char *, size_t);
+S operator"" _y(wchar_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 @_Zli2_yw({{.*}} 97)
   // CHECK: call void @_ZN1SD1Ev({{.*}}) nounwind
   // CHECK: call void @_ZN1SD1Ev({{.*}}) nounwind
-  "foo"_x, "bar"_x;
+  // CHECK: call void @_ZN1SD1Ev({{.*}}) nounwind
+  "foo"_x, "bar"_x, L'a'_y;
 }
 
 template<typename T> auto g(T t) -> decltype("foo"_x(t)) { return "foo"_x(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=152277&r1=152276&r2=152277&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp (original)
+++ cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp Wed Mar  7 19:34:56 2012
@@ -59,14 +59,37 @@
   (void)"test"_id "test" L"test";
 }
 
-enum class LitKind { CharStr, WideStr, Char16Str, Char32Str };
+enum class LitKind { Char, WideChar, Char16, Char32, CharStr, WideStr, Char16Str, Char32Str };
+constexpr LitKind operator"" _kind(char p) { return LitKind::Char; }
+constexpr LitKind operator"" _kind(wchar_t p) { return LitKind::WideChar; }
+constexpr LitKind operator"" _kind(char16_t p) { return LitKind::Char16; }
+constexpr LitKind operator"" _kind(char32_t p) { return LitKind::Char32; }
 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('x'_kind == LitKind::Char, "");
+static_assert(L'x'_kind == LitKind::WideChar, "");
+static_assert(u'x'_kind == LitKind::Char16, "");
+static_assert(U'x'_kind == LitKind::Char32, "");
 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, "");
+
+// Test source location for suffix is known
+const char *p =
+  "foo\nbar" R"x(
+  erk
+  flux
+  )x" "eep\x1f"\
+_no_such_suffix // expected-error {{'_no_such_suffix'}}
+"and a bit more"
+"and another suffix"_no_such_suffix;
+
+// And for character literals
+char c =
+  '\x14'\
+_no_such_suffix; // expected-error {{'_no_such_suffix'}}





More information about the cfe-commits mailing list