diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-08 02:39:21 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-08 02:39:21 +0000 |
commit | 0df56f4a9000cd1e7227059b95ffefa4435b0760 (patch) | |
tree | d4b662208056265251cddd216a467b284c98e191 | |
parent | 226b70c154fa1984ff189c434fefa1fee0af68df (diff) | |
download | bcm5719-llvm-0df56f4a9000cd1e7227059b95ffefa4435b0760.tar.gz bcm5719-llvm-0df56f4a9000cd1e7227059b95ffefa4435b0760.zip |
Implement C++11 [lex.ext]p10 for string and character literals: a ud-suffix not
starting with an underscore is ill-formed.
Since this rule rejects programs that were using <inttypes.h>'s macros, recover
from this error by treating the ud-suffix as a separate preprocessing-token,
with a DefaultError ExtWarn. The approach of treating such cases as two tokens
is under discussion for standardization, but is in any case a conforming
extension and allows existing codebases to keep building while the committee
makes up its mind.
Reword the warning on the definition of literal operators not starting with
underscores (which are, strangely, legal) to more explicitly state that such
operators can't be called by literals. Remove the special-case diagnostic for
hexfloats, since it was both triggering in the wrong cases and incorrect.
llvm-svn: 152287
-rw-r--r-- | clang/include/clang/Basic/DiagnosticGroups.td | 10 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticLexKinds.td | 7 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 10 | ||||
-rw-r--r-- | clang/lib/Lex/Lexer.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 27 | ||||
-rw-r--r-- | clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp | 4 | ||||
-rw-r--r-- | clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp | 8 | ||||
-rw-r--r-- | clang/test/CXX/over/over.oper/over.literal/p8.cpp | 8 | ||||
-rw-r--r-- | clang/test/FixIt/fixit-cxx0x.cpp | 5 | ||||
-rw-r--r-- | clang/test/FixIt/fixit-cxx11-compat.cpp | 4 | ||||
-rw-r--r-- | clang/test/Parser/cxx0x-literal-operators.cpp | 8 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx0x-compat.cpp | 6 |
12 files changed, 67 insertions, 45 deletions
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index c40ff031741..f5de122e0e3 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -79,7 +79,15 @@ def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>; // Name of this warning in GCC def : DiagGroup<"narrowing", [CXX11Narrowing]>; -def CXX11Compat : DiagGroup<"c++11-compat", [CXX11Narrowing]>; +def CXX11CompatReservedUserDefinedLiteral : + DiagGroup<"c++11-compat-reserved-user-defined-literal">; +def ReservedUserDefinedLiteral : + DiagGroup<"reserved-user-defined-literal", + [CXX11CompatReservedUserDefinedLiteral]>; + +def CXX11Compat : DiagGroup<"c++11-compat", + [CXX11Narrowing, + CXX11CompatReservedUserDefinedLiteral]>; def : DiagGroup<"c++0x-compat", [CXX11Compat]>; def : DiagGroup<"effc++">; diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index d31a48b6561..4fd55ef4e7b 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -134,6 +134,13 @@ def warn_cxx98_compat_unicode_literal : Warning< def warn_cxx11_compat_user_defined_literal : Warning< "identifier after literal will be treated as a user-defined literal suffix " "in C++11">, InGroup<CXX11Compat>, DefaultIgnore; +def warn_cxx11_compat_reserved_user_defined_literal : Warning< + "identifier after literal will be treated as a reserved user-defined literal " + "suffix in C++11">, + InGroup<CXX11CompatReservedUserDefinedLiteral>, DefaultIgnore; +def ext_reserved_user_defined_literal : ExtWarn< + "invalid suffix on literal; C++11 requires a space between literal and " + "identifier">, InGroup<ReservedUserDefinedLiteral>, DefaultError; def err_unsupported_string_concat : Error< "unsupported non-standard concatenation of string literals">; def err_string_concat_mixed_suffix : Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 07a94be54b7..0f5e7670ac1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4757,13 +4757,11 @@ 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>; def warn_user_literal_reserved : Warning< - "user-defined literals not starting with '_' are reserved by the " - "implementation">, InGroup<UserDefinedLiterals>; - + "user-defined literal suffixes not starting with '_' are reserved; " + "no literal will invoke this operator">, + InGroup<UserDefinedLiterals>; + // C++ conversion functions def err_conv_function_not_member : Error< "conversion function must be a non-static member function">; diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 0d388c6d01e..0b342389a03 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -1584,7 +1584,20 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr) { if (isIdentifierHead(C)) { if (!getFeatures().CPlusPlus0x) { if (!isLexingRawMode()) - Diag(CurPtr, diag::warn_cxx11_compat_user_defined_literal) + Diag(CurPtr, + C == '_' ? diag::warn_cxx11_compat_user_defined_literal + : diag::warn_cxx11_compat_reserved_user_defined_literal) + << FixItHint::CreateInsertion(getSourceLocation(CurPtr), " "); + return CurPtr; + } + + // C++11 [lex.ext]p10, [usrlit.suffix]p1: A program containing a ud-suffix + // that does not start with an underscore is ill-formed. As a conforming + // extension, we treat all such suffixes as if they had whitespace before + // them. + if (C != '_') { + if (!isLexingRawMode()) + Diag(CurPtr, diag::ext_reserved_user_defined_literal) << FixItHint::CreateInsertion(getSourceLocation(CurPtr), " "); return CurPtr; } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index abcaf983572..221cc6e53ee 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -9383,30 +9383,15 @@ FinishedParams: return true; } - StringRef LiteralName + StringRef LiteralName = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName(); if (LiteralName[0] != '_') { - // C++0x [usrlit.suffix]p1: - // Literal suffix identifiers that do not start with an underscore are - // reserved for future standardization. - bool IsHexFloat = true; - if (LiteralName.size() > 1 && - (LiteralName[0] == 'P' || LiteralName[0] == 'p')) { - for (unsigned I = 1, N = LiteralName.size(); I < N; ++I) { - if (!isdigit(LiteralName[I])) { - IsHexFloat = false; - break; - } - } - } - - if (IsHexFloat) - Diag(FnDecl->getLocation(), diag::warn_user_literal_hexfloat) - << LiteralName; - else - Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved); + // C++11 [usrlit.suffix]p1: + // Literal suffix identifiers that do not start with an underscore + // are reserved for future standardization. + Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved); } - + return false; } diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp index c167e822ebd..1c227a1b10d 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s -void operator "" p31(long double); // expected-warning{{user-defined literal with suffix 'p31' is preempted by C99 hexfloat extension}} +void operator "" p31(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} void operator "" _p31(long double); -long double operator "" pi(long double); // expected-warning{{user-defined literals not starting with '_' are reserved by the implementation}} +long double operator "" pi(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} float hexfloat = 0x1p31; // allow hexfloats diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp index 6652c9a890f..dc86fdf07f6 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++11 -verify %s using size_t = decltype(sizeof(int)); -void operator "" wibble(const char *); // expected-warning {{preempted}} -void operator "" wibble(const char *, size_t); // expected-warning {{preempted}} +void operator "" wibble(const char *); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} +void operator "" wibble(const char *, size_t); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} template<typename T> void f() { @@ -10,6 +10,6 @@ void f() { // FIXME: Reject these for the right reason. 123wibble; // expected-error {{suffix 'wibble'}} 123.0wibble; // expected-error {{suffix 'wibble'}} - ""wibble; - R"x("hello")x"wibble; + const char *p = ""wibble; // expected-error {{invalid suffix on literal; C++11 requires a space between literal and identifier}} expected-error {{expected ';'}} + const char *q = R"x("hello")x"wibble; // expected-error {{invalid suffix on literal; C++11 requires a space between literal and identifier}} expected-error {{expected ';'}} } diff --git a/clang/test/CXX/over/over.oper/over.literal/p8.cpp b/clang/test/CXX/over/over.oper/over.literal/p8.cpp index 1837aafc7bc..3f76082d10a 100644 --- a/clang/test/CXX/over/over.oper/over.literal/p8.cpp +++ b/clang/test/CXX/over/over.oper/over.literal/p8.cpp @@ -9,9 +9,11 @@ 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: Accept this as an extension, with a fix-it to add the space -float operator ""E(const char *); // expected-error {{C++11 requires a space between the "" and the user-defined suffix in a literal operator}} -float operator " " B(const char *); // expected-error {{must be '""'}} expected-warning {{hexfloat}} +float operator ""E(const char *); // expected-error {{C++11 requires a space between literal and identifier}} expected-warning {{reserved}} +float operator " " B(const char *); // expected-error {{must be '""'}} expected-warning {{reserved}} 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}} + +// FIXME: Accept this as an extension, with a fix-it to add the space +float operator ""_E(const char *); // expected-error {{C++11 requires a space between the "" and the user-defined suffix in a literal operator}} diff --git a/clang/test/FixIt/fixit-cxx0x.cpp b/clang/test/FixIt/fixit-cxx0x.cpp index da6bf2fe446..2bf9b20326e 100644 --- a/clang/test/FixIt/fixit-cxx0x.cpp +++ b/clang/test/FixIt/fixit-cxx0x.cpp @@ -60,3 +60,8 @@ void S2::f(int i) { (void)[] mutable { }; // expected-error{{lambda requires '()' before 'mutable'}} (void)[] -> int { }; // expected-error{{lambda requires '()' before return type}} } + +#define bar "bar" +const char *p = "foo"bar; // expected-error {{requires a space between}} +#define ord - '0' +int k = '4'ord; // expected-error {{requires a space between}} diff --git a/clang/test/FixIt/fixit-cxx11-compat.cpp b/clang/test/FixIt/fixit-cxx11-compat.cpp index 3a5ec84a454..39ae439d266 100644 --- a/clang/test/FixIt/fixit-cxx11-compat.cpp +++ b/clang/test/FixIt/fixit-cxx11-compat.cpp @@ -6,4 +6,6 @@ // This is a test of the code modification hints for C++11-compatibility problems. #define bar "bar" -const char *p = "foo"bar; // expected-warning {{will be treated as a user-defined literal suffix}} +const char *p = "foo"bar; // expected-warning {{will be treated as a reserved user-defined literal suffix}} +#define _bar "_bar" +const char *q = "foo"_bar; // expected-warning {{will be treated as a user-defined literal suffix}} diff --git a/clang/test/Parser/cxx0x-literal-operators.cpp b/clang/test/Parser/cxx0x-literal-operators.cpp index 4fcbad490d3..1881fcb7f09 100644 --- a/clang/test/Parser/cxx0x-literal-operators.cpp +++ b/clang/test/Parser/cxx0x-literal-operators.cpp @@ -1,6 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s void operator "" (const char *); // expected-error {{expected identifier}} -void operator "k" foo(const char *); // expected-error {{string literal after 'operator' must be '""'}} \ -// expected-warning{{user-defined literal with suffix 'foo' is preempted by C99 hexfloat extension}} -void operator "" tester (const char *); // expected-warning{{user-defined literal with suffix 'tester' is preempted by C99 hexfloat extension}} +void operator "k" foo(const char *); // \ + expected-error {{string literal after 'operator' must be '""'}} \ + expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} +void operator "" tester (const char *); // \ + expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} diff --git a/clang/test/SemaCXX/cxx0x-compat.cpp b/clang/test/SemaCXX/cxx0x-compat.cpp index 611dcc755ec..123008aadd8 100644 --- a/clang/test/SemaCXX/cxx0x-compat.cpp +++ b/clang/test/SemaCXX/cxx0x-compat.cpp @@ -32,8 +32,8 @@ t = { 1234 }; // expected-warning {{constant expression evaluates to 1234 which int printf(const char *, ...); typedef __typeof(sizeof(int)) size_t; void h(size_t foo, size_t bar) { - printf("foo is %"PRIuS", bar is %"PRIuS, foo, bar); // expected-warning 2{{identifier after literal will be treated as a user-defined literal suffix in C++11}} + printf("foo is %"PRIuS", bar is %"PRIuS, foo, bar); // expected-warning 2{{identifier after literal will be treated as a reserved user-defined literal suffix in C++11}} } -#define x + 1 -char c = 'x'x; // expected-warning {{will be treated as a user-defined literal suffix}} +#define _x + 1 +char c = 'x'_x; // expected-warning {{will be treated as a user-defined literal suffix}} |