diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-08-30 22:40:35 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-08-30 22:40:35 +0000 |
commit | 1155c42e7b1b4e401bb0a331a6d715d637958c75 (patch) | |
tree | d60d3c86444da53ad09279f9818ea5376cbd8c1a | |
parent | b89d5ed785e2eb7dd64aa38d481d939155f62c41 (diff) |
Allow C99 hexfloats in C++0x mode. This change resolves the standards
collision between C99 hexfloats and C++0x user-defined literals by
giving C99 hexfloats precedence. Also, warning about user-defined
literals that conflict with hexfloats and those that have names that
are reserved by the implementation. Fixes <rdar://problem/9940194>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138839 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticGroups.td | 4 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticLexKinds.td | 3 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 8 | ||||
-rw-r--r-- | lib/Lex/LiteralSupport.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 24 | ||||
-rw-r--r-- | test/CXX/lex/lex.literal/lex.ext/p1.cpp | 7 | ||||
-rw-r--r-- | test/Parser/cxx0x-literal-operators.cpp | 5 | ||||
-rw-r--r-- | test/SemaCXX/literal-operators.cpp | 38 |
8 files changed, 64 insertions, 31 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 462a3c71a6..35ff035aa0 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/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/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 1347ceb8c9..d40e2cde03 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/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<CXXHexFloats>; def ext_hexconstant_invalid : Extension< "hexadecimal floating constants are a C99 feature">; def ext_binary_literal : Extension< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 50b73984df..224853c34b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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<UserDefinedLiterals>; +def warn_user_literal_reserved : Warning< + "user-defined literals not starting with '_' are reserved by the " + "implementation">, InGroup<UserDefinedLiterals>; + // C++ conversion functions def err_conv_function_not_member : Error< "conversion function must be a non-static member function">; diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index b82dbd863b..d0e133a28a 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/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/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index cd4023eeda..df0a5226c0 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/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/test/CXX/lex/lex.literal/lex.ext/p1.cpp b/test/CXX/lex/lex.literal/lex.ext/p1.cpp new file mode 100644 index 0000000000..717228b31e --- /dev/null +++ b/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/test/Parser/cxx0x-literal-operators.cpp b/test/Parser/cxx0x-literal-operators.cpp index 30b290382c..a161374a41 100644 --- a/test/Parser/cxx0x-literal-operators.cpp +++ b/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/test/SemaCXX/literal-operators.cpp b/test/SemaCXX/literal-operators.cpp index ec585a61da..ab80c9a3d3 100644 --- a/test/SemaCXX/literal-operators.cpp +++ b/test/SemaCXX/literal-operators.cpp @@ -3,39 +3,39 @@ #include <stddef.h> 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 <char...> void operator "" good (); |