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
This commit is contained in:
Douglas Gregor 2011-08-30 22:40:35 +00:00
Родитель b89d5ed785
Коммит 1155c42e7b
8 изменённых файлов: 64 добавлений и 31 удалений

Просмотреть файл

@ -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">;

Просмотреть файл

@ -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<

Просмотреть файл

@ -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">;

Просмотреть файл

@ -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),

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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}}

Просмотреть файл

@ -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 ();