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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152211 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CXX/lex/lex.literal/lex.ext/p10.cpp b/test/CXX/lex/lex.literal/lex.ext/p10.cpp
index 7fbd9f8..6652c9a 100644
--- a/test/CXX/lex/lex.literal/lex.ext/p10.cpp
+++ b/test/CXX/lex/lex.literal/lex.ext/p10.cpp
@@ -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;
}
diff --git a/test/CXX/lex/lex.literal/lex.ext/p8.cpp b/test/CXX/lex/lex.literal/lex.ext/p8.cpp
index 2833769..d907822 100644
--- a/test/CXX/lex/lex.literal/lex.ext/p8.cpp
+++ b/test/CXX/lex/lex.literal/lex.ext/p8.cpp
@@ -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}}
diff --git a/test/CXX/lex/lex.literal/lex.ext/p9.cpp b/test/CXX/lex/lex.literal/lex.ext/p9.cpp
index e3de34d..65e27b4 100644
--- a/test/CXX/lex/lex.literal/lex.ext/p9.cpp
+++ b/test/CXX/lex/lex.literal/lex.ext/p9.cpp
@@ -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}}
}
diff --git a/test/CodeGenCXX/cxx11-user-defined-literal.cpp b/test/CodeGenCXX/cxx11-user-defined-literal.cpp
new file mode 100644
index 0000000..fbd3621
--- /dev/null
+++ b/test/CodeGenCXX/cxx11-user-defined-literal.cpp
@@ -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
diff --git a/test/PCH/cxx11-user-defined-literals.cpp b/test/PCH/cxx11-user-defined-literals.cpp
new file mode 100644
index 0000000..4a7c24b
--- /dev/null
+++ b/test/PCH/cxx11-user-defined-literals.cpp
@@ -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
diff --git a/test/Parser/cxx11-user-defined-literals.cpp b/test/Parser/cxx11-user-defined-literals.cpp
index c2d5af5..e3f79ec 100644
--- a/test/Parser/cxx11-user-defined-literals.cpp
+++ b/test/Parser/cxx11-user-defined-literals.cpp
@@ -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, "");
diff --git a/test/SemaCXX/cxx11-ast-print.cpp b/test/SemaCXX/cxx11-ast-print.cpp
new file mode 100644
index 0000000..1f6f947
--- /dev/null
+++ b/test/SemaCXX/cxx11-ast-print.cpp
@@ -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;