зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
b89d5ed785
Коммит
1155c42e7b
|
@ -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 ();
|
||||
|
|
Загрузка…
Ссылка в новой задаче