diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 462a3c71a60ebdb23941c70158cc45142d9794f5..35ff035aa05ef8affc14e7d754ac03e616941226 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -54,10 +54,9 @@ def ExtraTokens : DiagGroup<"extra-tokens">; def FormatExtraArgs : DiagGroup<"format-extra-args">; def FormatZeroLength : DiagGroup<"format-zero-length">; -def CXXHexFloats : DiagGroup<"c++-hex-floats">; def CXX0xNarrowing : DiagGroup<"c++0x-narrowing">; -def CXX0xCompat : DiagGroup<"c++0x-compat", [CXXHexFloats, CXX0xNarrowing]>; +def CXX0xCompat : DiagGroup<"c++0x-compat", [CXX0xNarrowing]>; def : DiagGroup<"effc++">; def ExitTimeDestructors : DiagGroup<"exit-time-destructors">; def FourByteMultiChar : DiagGroup<"four-char-constants">; @@ -169,6 +168,7 @@ def UnusedResult : DiagGroup<"unused-result">; def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult]>; def UnusedVariable : DiagGroup<"unused-variable">; def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">; +def UserDefinedLiterals : DiagGroup<"user-defined-literals">; def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">; def Reorder : DiagGroup<"reorder">; def UndeclaredSelector : DiagGroup<"undeclared-selector">; diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index 1347ceb8c9d2a0a94898dc8bf05c65ca96098080..d40e2cde03061edd496f5b73534be9dc8902c387 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -94,9 +94,6 @@ def err_exponent_has_no_digits : Error<"exponent has no digits">; def ext_imaginary_constant : Extension<"imaginary constants are an extension">; def err_hexconstant_requires_exponent : Error< "hexadecimal floating constants require an exponent">; -def ext_hexconstant_cplusplus : Extension< - "hexadecimal floating constants are a C99 feature that is incompatible with " - "C++0x">, InGroup; def ext_hexconstant_invalid : Extension< "hexadecimal floating constants are a C99 feature">; def ext_binary_literal : Extension< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 50b73984df59c18ee72cbf23574c2e853f0bd1f3..224853c34b7b4e51bb0ecf88f73c3dddf2caafee 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4152,7 +4152,13 @@ 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 warn_user_literal_hexfloat : Warning< + "user-defined literal with suffix '%0' is preempted by C99 hexfloat " + "extension">, InGroup; +def warn_user_literal_reserved : Warning< + "user-defined literals not starting with '_' are reserved by the " + "implementation">, InGroup; + // 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/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index b82dbd863bfba8cd1d1968bfee9286cecc1ca205..d0e133a28a68d770ca45f1e607e79f3b228c82d3 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -546,7 +546,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { } // A binary exponent can appear with or with a '.'. If dotted, the // binary exponent is required. - if ((*s == 'p' || *s == 'P') && !PP.getLangOptions().CPlusPlus0x) { + if (*s == 'p' || *s == 'P') { const char *Exponent = s; s++; saw_exponent = true; @@ -563,9 +563,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { // In C++0x, we cannot support hexadecmial floating literals because // they conflict with user-defined literals, so we warn in previous // versions of C++ by default. - if (PP.getLangOptions().CPlusPlus) - PP.Diag(TokLoc, diag::ext_hexconstant_cplusplus); - else if (!PP.getLangOptions().HexFloats) + if (!PP.getLangOptions().HexFloats) PP.Diag(TokLoc, diag::ext_hexconstant_invalid); } else if (saw_period) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index cd4023eeda2276d5a82d8dec5e5144981bbcc312..df0a5226c0f02ed426ad1d4ef194b04b221a4967 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -9048,6 +9048,30 @@ FinishedParams: return true; } + 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); + } + 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 new file mode 100644 index 0000000000000000000000000000000000000000..717228b31e28129682092ca42b66aee536de84bc --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s + +int * operator "" p31(long double); // expected-warning{{user-defined literal with suffix 'p31' is preempted by C99 hexfloat extension}} +long double operator "" _p31(long double); +long double operator "" pi(long double); // expected-warning{{user-defined literals not starting with '_' are reserved by the implementation}} + +float hexfloat = 0x1p31; // allow hexfloats diff --git a/clang/test/Parser/cxx0x-literal-operators.cpp b/clang/test/Parser/cxx0x-literal-operators.cpp index 30b290382cb48d092cbf63e7fb5214ff8fab893c..a161374a41d864ef6d11a8a8a8c1e1bb570456e7 100644 --- a/clang/test/Parser/cxx0x-literal-operators.cpp +++ b/clang/test/Parser/cxx0x-literal-operators.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s void operator "" (const char *); // expected-error {{expected identifier}} -void operator "k" foo(const char *); // expected-error {{string literal after 'operator' must be '""'}} -void operator "" tester (const char *); +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}} diff --git a/clang/test/SemaCXX/literal-operators.cpp b/clang/test/SemaCXX/literal-operators.cpp index ec585a61da9fab8ff2ca39f84ada477dc56a0d0b..ab80c9a3d35f7ec1dc29cecc4b003a7604d12064 100644 --- a/clang/test/SemaCXX/literal-operators.cpp +++ b/clang/test/SemaCXX/literal-operators.cpp @@ -3,39 +3,39 @@ #include struct tag { - void operator "" tag_bad (const char *); // expected-error {{literal operator 'operator "" tag_bad' must be in a namespace or global scope}} - friend void operator "" tag_good (const char *); + void operator "" _tag_bad (const char *); // expected-error {{literal operator 'operator "" _tag_bad' must be in a namespace or global scope}} + friend void operator "" _tag_good (const char *); }; -namespace ns { void operator "" ns_good (const char *); } +namespace ns { void operator "" _ns_good (const char *); } // Check extern "C++" declarations -extern "C++" void operator "" extern_good (const char *); -extern "C++" { void operator "" extern_good (const char *); } +extern "C++" void operator "" _extern_good (const char *); +extern "C++" { void operator "" _extern_good (const char *); } -void fn () { void operator "" fn_bad (const char *); } // expected-error {{literal operator 'operator "" fn_bad' must be in a namespace or global scope}} +void fn () { void operator "" _fn_bad (const char *); } // expected-error {{literal operator 'operator "" _fn_bad' must be in a namespace or global scope}} // One-param declarations (const char * was already checked) -void operator "" good (char); -void operator "" good (wchar_t); -void operator "" good (char16_t); -void operator "" good (char32_t); -void operator "" good (unsigned long long); -void operator "" good (long double); +void operator "" _good (char); +void operator "" _good (wchar_t); +void operator "" _good (char16_t); +void operator "" _good (char32_t); +void operator "" _good (unsigned long long); +void operator "" _good (long double); // Two-param declarations -void operator "" good (const char *, size_t); -void operator "" good (const wchar_t *, size_t); -void operator "" good (const char16_t *, size_t); -void operator "" good (const char32_t *, size_t); +void operator "" _good (const char *, size_t); +void operator "" _good (const wchar_t *, size_t); +void operator "" _good (const char16_t *, size_t); +void operator "" _good (const char32_t *, size_t); // Check typedef and array equivalences -void operator "" good (const char[]); +void operator "" _good (const char[]); typedef const char c; -void operator "" good (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); // Template delcaration (not implemented yet) // template void operator "" good ();