diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 15 | ||||
-rw-r--r-- | test/CXX/over/over.oper/over.literal/p2.cpp | 27 | ||||
-rw-r--r-- | test/CXX/over/over.oper/over.literal/p3.cpp | 39 | ||||
-rw-r--r-- | test/CXX/over/over.oper/over.literal/p5.cpp | 18 | ||||
-rw-r--r-- | test/CXX/over/over.oper/over.literal/p6.cpp | 13 | ||||
-rw-r--r-- | test/CXX/over/over.oper/over.literal/p7.cpp | 16 | ||||
-rw-r--r-- | test/CXX/over/over.oper/over.literal/p8.cpp | 17 | ||||
-rw-r--r-- | test/SemaCXX/literal-operators.cpp | 6 |
9 files changed, 145 insertions, 8 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1c749e3eb7..5d3ff2a4af 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4684,6 +4684,8 @@ def err_literal_operator_outside_namespace : Error< // FIXME: This diagnostic sucks def err_literal_operator_params : Error< "parameter declaration for literal operator %0 is not valid">; +def err_literal_operator_extern_c : Error< + "literal operator must have C++ linkage">; def warn_user_literal_hexfloat : Warning< "user-defined literal with suffix '%0' is preempted by C99 hexfloat " "extension">, InGroup<UserDefinedLiterals>; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 4f0e160950..34648805f9 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -9297,12 +9297,17 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { return true; } + if (FnDecl->isExternC()) { + Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c); + return true; + } + bool Valid = false; // template <char...> type operator "" name() is the only valid template // signature, and the only valid signature with no parameters. - if (FnDecl->param_size() == 0) { - if (FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate()) { + if (FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate()) { + if (FnDecl->param_size() == 0) { // Must have only one template parameter TemplateParameterList *Params = TpDecl->getTemplateParameters(); if (Params->size() == 1) { @@ -9315,11 +9320,11 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { Valid = true; } } - } else { + } else if (FnDecl->param_size()) { // Check the first parameter FunctionDecl::param_iterator Param = FnDecl->param_begin(); - QualType T = (*Param)->getType(); + QualType T = (*Param)->getType().getUnqualifiedType(); // unsigned long long int, long double, and any character type are allowed // as the only parameters. @@ -9339,7 +9344,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { if (!PT) goto FinishedParams; T = PT->getPointeeType(); - if (!T.isConstQualified()) + if (!T.isConstQualified() || T.isVolatileQualified()) goto FinishedParams; T = T.getUnqualifiedType(); diff --git a/test/CXX/over/over.oper/over.literal/p2.cpp b/test/CXX/over/over.oper/over.literal/p2.cpp new file mode 100644 index 0000000000..fb11ca5578 --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p2.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +void operator "" _a(const char *); + +namespace N { + using ::operator "" _a; + + void operator "" _b(const char *); +} + +using N::operator "" _b; + +class C { + void operator "" _c(const char *); // expected-error {{must be in a namespace or global scope}} + + friend void operator "" _d(const char *); +}; + +int operator "" _e; // expected-error {{cannot be the name of a variable}} + +void f() { + int operator "" _f; // expected-error {{cannot be the name of a variable}} +} + +extern "C++" { + void operator "" _g(const char *); +} diff --git a/test/CXX/over/over.oper/over.literal/p3.cpp b/test/CXX/over/over.oper/over.literal/p3.cpp new file mode 100644 index 0000000000..0b5323b473 --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p3.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +using size_t = decltype(sizeof(int)); + +// Acceptable parameter declarations +char operator "" _a(const char *); +char operator "" _a(const char []); +char operator "" _a(unsigned long long); +char operator "" _a(long double); +char operator "" _a(char); +char operator "" _a(const volatile char); +char operator "" _a(wchar_t); +char operator "" _a(char16_t); +char operator "" _a(char32_t); +char operator "" _a(const char *, size_t); +char operator "" _a(const wchar_t *, size_t); +char operator "" _a(const char16_t *, size_t); +char operator "" _a(const char32_t *, size_t); +char operator "" _a(const char [32], size_t); + +// Unacceptable parameter declarations +char operator "" _b(); // expected-error {{parameter}} +char operator "" _b(const wchar_t *); // expected-error {{parameter}} +char operator "" _b(long long); // expected-error {{parameter}} +char operator "" _b(double); // expected-error {{parameter}} +char operator "" _b(short); // expected-error {{parameter}} +char operator "" _a(char, int = 0); // expected-error {{parameter}} +char operator "" _b(unsigned short); // expected-error {{parameter}} +char operator "" _b(signed char); // expected-error {{parameter}} +char operator "" _b(unsigned char); // expected-error {{parameter}} +char operator "" _b(const short *, size_t); // expected-error {{parameter}} +char operator "" _b(const unsigned short *, size_t); // expected-error {{parameter}} +char operator "" _b(const signed char *, size_t); // expected-error {{parameter}} +char operator "" _b(const unsigned char *, size_t); // expected-error {{parameter}} +char operator "" _a(const volatile char *, size_t); // expected-error {{parameter}} +char operator "" _a(volatile wchar_t *, size_t); // expected-error {{parameter}} +char operator "" _a(char16_t *, size_t); // expected-error {{parameter}} +char operator "" _a(const char32_t *, size_t, bool = false); // expected-error {{parameter}} +char operator "" _a(const char *, signed long); // expected-error {{parameter}} diff --git a/test/CXX/over/over.oper/over.literal/p5.cpp b/test/CXX/over/over.oper/over.literal/p5.cpp new file mode 100644 index 0000000000..7a782fca91 --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p5.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +using size_t = decltype(sizeof(int)); +template<char...> struct S {}; + +template<char...> void operator "" _a(); +template<char... C> S<C...> operator "" _a(); + +template<typename T> struct U { + // FIXME: It's not entirely clear whether this is intended to be legal. + friend U operator "" _a(const T *, size_t); // expected-error {{parameter}} +}; + +template<char... C, int N = 0> void operator "" _b(); // expected-error {{parameter}} +template<char... C> void operator "" _b(int N = 0); // expected-error {{parameter}} +template<char, char...> void operator "" _b(); // expected-error {{parameter}} +template<typename T> T operator "" _b(const char *); // expected-error {{parameter}} +template<typename T> int operator "" _b(const T *, size_t); // expected-error {{parameter}} diff --git a/test/CXX/over/over.oper/over.literal/p6.cpp b/test/CXX/over/over.oper/over.literal/p6.cpp new file mode 100644 index 0000000000..6bfb8560d6 --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p6.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +extern "C" void operator "" _a(const char *); // expected-error {{must have C++ linkage}} +extern "C" template<char...> void operator "" _b(); // expected-error {{must have C++ linkage}} + +extern "C" { + void operator "" _c(const char *); // expected-error {{must have C++ linkage}} + template<char...> void operator "" _d(); // expected-error {{must have C++ linkage}} + namespace N { + void operator "" _e(const char *); // expected-error {{must have C++ linkage}} + template<char...> void operator "" _f(); // expected-error {{must have C++ linkage}} + } +} diff --git a/test/CXX/over/over.oper/over.literal/p7.cpp b/test/CXX/over/over.oper/over.literal/p7.cpp new file mode 100644 index 0000000000..72411b954e --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p7.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +constexpr int operator "" _a(const char *c) { + return c[0]; +} + +static_assert(operator "" _a("foo") == 'f', ""); + +void puts(const char *); +static inline void operator "" _puts(const char *c) { + puts(c); +} +void f() { + operator "" _puts("foo"); + operator "" _puts("bar"); +} diff --git a/test/CXX/over/over.oper/over.literal/p8.cpp b/test/CXX/over/over.oper/over.literal/p8.cpp new file mode 100644 index 0000000000..fe94b5348b --- /dev/null +++ b/test/CXX/over/over.oper/over.literal/p8.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +struct string; +namespace std { + using size_t = decltype(sizeof(int)); +} + +void operator "" _km(long double); // ok +string operator "" _i18n(const char*, std::size_t); // ok +// FIXME: This should be accepted once we support UCNs +template<char...> int operator "" \u03C0(); // ok, UCN for lowercase pi // expected-error {{expected identifier}} +// FIXME: This should be rejected once we lex user-defined literal suffices +float operator ""E(const char *); // expected-warning {{hexfloat}} +float operator " " B(const char *); // expected-error {{must be '""'}} expected-warning {{hexfloat}} +string operator "" 5X(const char *, std::size_t); // expected-error {{expected identifier}} +double operator "" _miles(double); // expected-error {{parameter}} +template<char...> int operator "" j(const char*); // expected-error {{parameter}} diff --git a/test/SemaCXX/literal-operators.cpp b/test/SemaCXX/literal-operators.cpp index 06ef49fc0a..745a433ac5 100644 --- a/test/SemaCXX/literal-operators.cpp +++ b/test/SemaCXX/literal-operators.cpp @@ -35,9 +35,9 @@ typedef const char c; void operator "" _good (c*); // Check extra cv-qualifiers -void operator "" _cv_good (volatile const char *, const size_t); +void operator "" _cv_good (volatile const char *, const size_t); // expected-error {{parameter declaration for literal operator 'operator "" _cv_good' is not valid}} -// Template delcaration (not implemented yet) -// template <char...> void operator "" good (); +// Template declaration +template <char...> void operator "" _good (); // FIXME: Test some invalid decls that might crop up. |