forked from OSchip/llvm-project
C++1y literal suffix support:
* Allow ns, us, ms, s, min, h as numeric ud-suffixes * Allow s as string ud-suffix llvm-svn: 186933
This commit is contained in:
parent
6030a65039
commit
f4198b7598
|
@ -5804,8 +5804,8 @@ def err_literal_operator_params : Error<
|
|||
def err_literal_operator_extern_c : Error<
|
||||
"literal operator must have C++ linkage">;
|
||||
def warn_user_literal_reserved : Warning<
|
||||
"user-defined literal suffixes not starting with '_' are reserved; "
|
||||
"no literal will invoke this operator">,
|
||||
"user-defined literal suffixes not starting with '_' are reserved"
|
||||
"%select{; no literal will invoke this operator|}0">,
|
||||
InGroup<UserDefinedLiterals>;
|
||||
|
||||
// C++ conversion functions
|
||||
|
|
|
@ -569,7 +569,8 @@ private:
|
|||
|
||||
void SkipBytes(unsigned Bytes, bool StartOfLine);
|
||||
|
||||
const char *LexUDSuffix(Token &Result, const char *CurPtr);
|
||||
const char *LexUDSuffix(Token &Result, const char *CurPtr,
|
||||
bool IsStringLiteral);
|
||||
|
||||
// Helper functions to lex the remainder of a token of the specific type.
|
||||
void LexIdentifier (Token &Result, const char *CurPtr);
|
||||
|
|
|
@ -79,6 +79,8 @@ public:
|
|||
return SuffixBegin - ThisTokBegin;
|
||||
}
|
||||
|
||||
static bool isValidUDSuffix(const LangOptions &LangOpts, StringRef Suffix);
|
||||
|
||||
unsigned getRadix() const { return radix; }
|
||||
|
||||
/// GetIntegerValue - Convert this numeric literal value to an APInt that
|
||||
|
|
|
@ -1586,7 +1586,8 @@ void Lexer::LexNumericConstant(Token &Result, const char *CurPtr) {
|
|||
|
||||
/// LexUDSuffix - Lex the ud-suffix production for user-defined literal suffixes
|
||||
/// in C++11, or warn on a ud-suffix in C++98.
|
||||
const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr) {
|
||||
const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr,
|
||||
bool IsStringLiteral) {
|
||||
assert(getLangOpts().CPlusPlus);
|
||||
|
||||
// Maximally munch an identifier. FIXME: UCNs.
|
||||
|
@ -1606,7 +1607,18 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr) {
|
|||
// 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 != '_') {
|
||||
bool IsUDSuffix = false;
|
||||
if (C == '_')
|
||||
IsUDSuffix = true;
|
||||
else if (IsStringLiteral && C == 's' && getLangOpts().CPlusPlus1y) {
|
||||
// In C++1y, "s" is a valid ud-suffix for a string literal.
|
||||
unsigned NextSize;
|
||||
if (!isIdentifierBody(getCharAndSizeNoWarn(CurPtr + Size, NextSize,
|
||||
getLangOpts())))
|
||||
IsUDSuffix = true;
|
||||
}
|
||||
|
||||
if (!IsUDSuffix) {
|
||||
if (!isLexingRawMode())
|
||||
Diag(CurPtr, getLangOpts().MicrosoftMode ?
|
||||
diag::ext_ms_reserved_user_defined_literal :
|
||||
|
@ -1667,7 +1679,7 @@ void Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
|
|||
|
||||
// If we are in C++11, lex the optional ud-suffix.
|
||||
if (getLangOpts().CPlusPlus)
|
||||
CurPtr = LexUDSuffix(Result, CurPtr);
|
||||
CurPtr = LexUDSuffix(Result, CurPtr, true);
|
||||
|
||||
// If a nul character existed in the string, warn about it.
|
||||
if (NulCharacter && !isLexingRawMode())
|
||||
|
@ -1750,7 +1762,7 @@ void Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr,
|
|||
|
||||
// If we are in C++11, lex the optional ud-suffix.
|
||||
if (getLangOpts().CPlusPlus)
|
||||
CurPtr = LexUDSuffix(Result, CurPtr);
|
||||
CurPtr = LexUDSuffix(Result, CurPtr, true);
|
||||
|
||||
// Update the location of token as well as BufferPtr.
|
||||
const char *TokStart = BufferPtr;
|
||||
|
@ -1840,7 +1852,7 @@ void Lexer::LexCharConstant(Token &Result, const char *CurPtr,
|
|||
|
||||
// If we are in C++11, lex the optional ud-suffix.
|
||||
if (getLangOpts().CPlusPlus)
|
||||
CurPtr = LexUDSuffix(Result, CurPtr);
|
||||
CurPtr = LexUDSuffix(Result, CurPtr, false);
|
||||
|
||||
// If a nul character existed in the character, warn about it.
|
||||
if (NulCharacter && !isLexingRawMode())
|
||||
|
|
|
@ -413,10 +413,12 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
|
|||
/// decimal-constant integer-suffix
|
||||
/// octal-constant integer-suffix
|
||||
/// hexadecimal-constant integer-suffix
|
||||
/// binary-literal integer-suffix [GNU, C++1y]
|
||||
/// user-defined-integer-literal: [C++11 lex.ext]
|
||||
/// decimal-literal ud-suffix
|
||||
/// octal-literal ud-suffix
|
||||
/// hexadecimal-literal ud-suffix
|
||||
/// binary-literal ud-suffix [GNU, C++1y]
|
||||
/// decimal-constant:
|
||||
/// nonzero-digit
|
||||
/// decimal-constant digit
|
||||
|
@ -428,6 +430,10 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
|
|||
/// hexadecimal-constant hexadecimal-digit
|
||||
/// hexadecimal-prefix: one of
|
||||
/// 0x 0X
|
||||
/// binary-literal:
|
||||
/// 0b binary-digit
|
||||
/// 0B binary-digit
|
||||
/// binary-literal binary-digit
|
||||
/// integer-suffix:
|
||||
/// unsigned-suffix [long-suffix]
|
||||
/// unsigned-suffix [long-long-suffix]
|
||||
|
@ -441,6 +447,9 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
|
|||
/// 0 1 2 3 4 5 6 7 8 9
|
||||
/// a b c d e f
|
||||
/// A B C D E F
|
||||
/// binary-digit:
|
||||
/// 0
|
||||
/// 1
|
||||
/// unsigned-suffix: one of
|
||||
/// u U
|
||||
/// long-suffix: one of
|
||||
|
@ -515,6 +524,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
|
|||
// Parse the suffix. At this point we can classify whether we have an FP or
|
||||
// integer constant.
|
||||
bool isFPConstant = isFloatingLiteral();
|
||||
const char *ImaginarySuffixLoc = 0;
|
||||
|
||||
// Loop over all of the characters of the suffix. If we see something bad,
|
||||
// we break out of the loop.
|
||||
|
@ -598,9 +608,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
|
|||
case 'j':
|
||||
case 'J':
|
||||
if (isImaginary) break; // Cannot be repeated.
|
||||
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
|
||||
diag::ext_imaginary_constant);
|
||||
isImaginary = true;
|
||||
ImaginarySuffixLoc = s;
|
||||
continue; // Success.
|
||||
}
|
||||
// If we reached here, there was an error or a ud-suffix.
|
||||
|
@ -608,9 +617,17 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
|
|||
}
|
||||
|
||||
if (s != ThisTokEnd) {
|
||||
if (PP.getLangOpts().CPlusPlus11 && s == SuffixBegin && *s == '_') {
|
||||
// We have a ud-suffix! By C++11 [lex.ext]p10, ud-suffixes not starting
|
||||
// with an '_' are ill-formed.
|
||||
if (isValidUDSuffix(PP.getLangOpts(),
|
||||
StringRef(SuffixBegin, ThisTokEnd - SuffixBegin))) {
|
||||
// Any suffix pieces we might have parsed are actually part of the
|
||||
// ud-suffix.
|
||||
isLong = false;
|
||||
isUnsigned = false;
|
||||
isLongLong = false;
|
||||
isFloat = false;
|
||||
isImaginary = false;
|
||||
isMicrosoftInteger = false;
|
||||
|
||||
saw_ud_suffix = true;
|
||||
return;
|
||||
}
|
||||
|
@ -623,6 +640,35 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
|
|||
hadError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isImaginary) {
|
||||
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc,
|
||||
ImaginarySuffixLoc - ThisTokBegin),
|
||||
diag::ext_imaginary_constant);
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
|
||||
/// suffixes as ud-suffixes, because the diagnostic experience is better if we
|
||||
/// treat it as an invalid suffix.
|
||||
bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts,
|
||||
StringRef Suffix) {
|
||||
if (!LangOpts.CPlusPlus11 || Suffix.empty())
|
||||
return false;
|
||||
|
||||
// By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid.
|
||||
if (Suffix[0] == '_')
|
||||
return true;
|
||||
|
||||
// In C++11, there are no library suffixes.
|
||||
if (!LangOpts.CPlusPlus1y)
|
||||
return false;
|
||||
|
||||
// In C++1y, "s", "h", "min", "ms", "us", and "ns" are used in the library.
|
||||
return llvm::StringSwitch<bool>(Suffix)
|
||||
.Cases("h", "min", "s", true)
|
||||
.Cases("ms", "us", "ns", true)
|
||||
.Default(false);
|
||||
}
|
||||
|
||||
/// ParseNumberStartingWithZero - This method is called when the first character
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "clang/AST/TypeOrdering.h"
|
||||
#include "clang/Basic/PartialDiagnostic.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Lex/LiteralSupport.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Sema/CXXFieldCollector.h"
|
||||
#include "clang/Sema/DeclSpec.h"
|
||||
|
@ -10650,7 +10651,8 @@ FinishedParams:
|
|||
// 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);
|
||||
Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
|
||||
<< NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// RUN: %clang_cc1 -std=c++1y %s -include %s -verify
|
||||
|
||||
#ifndef INCLUDED
|
||||
#define INCLUDED
|
||||
|
||||
#pragma clang system_header
|
||||
namespace std {
|
||||
using size_t = decltype(sizeof(0));
|
||||
|
||||
struct duration {};
|
||||
duration operator"" ns(unsigned long long);
|
||||
duration operator"" us(unsigned long long);
|
||||
duration operator"" ms(unsigned long long);
|
||||
duration operator"" s(unsigned long long);
|
||||
duration operator"" min(unsigned long long);
|
||||
duration operator"" h(unsigned long long);
|
||||
|
||||
struct string {};
|
||||
string operator"" s(const char*, size_t);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
using namespace std;
|
||||
duration a = 1ns, b = 1us, c = 1ms, d = 1s, e = 1min, f = 1h;
|
||||
string s = "foo"s;
|
||||
char error = 'x's; // expected-error {{invalid suffix}} expected-error {{expected ';'}}
|
||||
|
||||
int _1z = 1z; // expected-error {{invalid suffix}}
|
||||
int _1b = 1b; // expected-error {{invalid digit}}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue