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<
|
def err_literal_operator_extern_c : Error<
|
||||||
"literal operator must have C++ linkage">;
|
"literal operator must have C++ linkage">;
|
||||||
def warn_user_literal_reserved : Warning<
|
def warn_user_literal_reserved : Warning<
|
||||||
"user-defined literal suffixes not starting with '_' are reserved; "
|
"user-defined literal suffixes not starting with '_' are reserved"
|
||||||
"no literal will invoke this operator">,
|
"%select{; no literal will invoke this operator|}0">,
|
||||||
InGroup<UserDefinedLiterals>;
|
InGroup<UserDefinedLiterals>;
|
||||||
|
|
||||||
// C++ conversion functions
|
// C++ conversion functions
|
||||||
|
|
|
@ -569,7 +569,8 @@ private:
|
||||||
|
|
||||||
void SkipBytes(unsigned Bytes, bool StartOfLine);
|
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.
|
// Helper functions to lex the remainder of a token of the specific type.
|
||||||
void LexIdentifier (Token &Result, const char *CurPtr);
|
void LexIdentifier (Token &Result, const char *CurPtr);
|
||||||
|
|
|
@ -79,6 +79,8 @@ public:
|
||||||
return SuffixBegin - ThisTokBegin;
|
return SuffixBegin - ThisTokBegin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isValidUDSuffix(const LangOptions &LangOpts, StringRef Suffix);
|
||||||
|
|
||||||
unsigned getRadix() const { return radix; }
|
unsigned getRadix() const { return radix; }
|
||||||
|
|
||||||
/// GetIntegerValue - Convert this numeric literal value to an APInt that
|
/// 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
|
/// LexUDSuffix - Lex the ud-suffix production for user-defined literal suffixes
|
||||||
/// in C++11, or warn on a ud-suffix in C++98.
|
/// 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);
|
assert(getLangOpts().CPlusPlus);
|
||||||
|
|
||||||
// Maximally munch an identifier. FIXME: UCNs.
|
// 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
|
// 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
|
// extension, we treat all such suffixes as if they had whitespace before
|
||||||
// them.
|
// 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())
|
if (!isLexingRawMode())
|
||||||
Diag(CurPtr, getLangOpts().MicrosoftMode ?
|
Diag(CurPtr, getLangOpts().MicrosoftMode ?
|
||||||
diag::ext_ms_reserved_user_defined_literal :
|
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 we are in C++11, lex the optional ud-suffix.
|
||||||
if (getLangOpts().CPlusPlus)
|
if (getLangOpts().CPlusPlus)
|
||||||
CurPtr = LexUDSuffix(Result, CurPtr);
|
CurPtr = LexUDSuffix(Result, CurPtr, true);
|
||||||
|
|
||||||
// If a nul character existed in the string, warn about it.
|
// If a nul character existed in the string, warn about it.
|
||||||
if (NulCharacter && !isLexingRawMode())
|
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 we are in C++11, lex the optional ud-suffix.
|
||||||
if (getLangOpts().CPlusPlus)
|
if (getLangOpts().CPlusPlus)
|
||||||
CurPtr = LexUDSuffix(Result, CurPtr);
|
CurPtr = LexUDSuffix(Result, CurPtr, true);
|
||||||
|
|
||||||
// Update the location of token as well as BufferPtr.
|
// Update the location of token as well as BufferPtr.
|
||||||
const char *TokStart = 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 we are in C++11, lex the optional ud-suffix.
|
||||||
if (getLangOpts().CPlusPlus)
|
if (getLangOpts().CPlusPlus)
|
||||||
CurPtr = LexUDSuffix(Result, CurPtr);
|
CurPtr = LexUDSuffix(Result, CurPtr, false);
|
||||||
|
|
||||||
// If a nul character existed in the character, warn about it.
|
// If a nul character existed in the character, warn about it.
|
||||||
if (NulCharacter && !isLexingRawMode())
|
if (NulCharacter && !isLexingRawMode())
|
||||||
|
|
|
@ -413,10 +413,12 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
|
||||||
/// decimal-constant integer-suffix
|
/// decimal-constant integer-suffix
|
||||||
/// octal-constant integer-suffix
|
/// octal-constant integer-suffix
|
||||||
/// hexadecimal-constant integer-suffix
|
/// hexadecimal-constant integer-suffix
|
||||||
|
/// binary-literal integer-suffix [GNU, C++1y]
|
||||||
/// user-defined-integer-literal: [C++11 lex.ext]
|
/// user-defined-integer-literal: [C++11 lex.ext]
|
||||||
/// decimal-literal ud-suffix
|
/// decimal-literal ud-suffix
|
||||||
/// octal-literal ud-suffix
|
/// octal-literal ud-suffix
|
||||||
/// hexadecimal-literal ud-suffix
|
/// hexadecimal-literal ud-suffix
|
||||||
|
/// binary-literal ud-suffix [GNU, C++1y]
|
||||||
/// decimal-constant:
|
/// decimal-constant:
|
||||||
/// nonzero-digit
|
/// nonzero-digit
|
||||||
/// decimal-constant digit
|
/// decimal-constant digit
|
||||||
|
@ -428,6 +430,10 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
|
||||||
/// hexadecimal-constant hexadecimal-digit
|
/// hexadecimal-constant hexadecimal-digit
|
||||||
/// hexadecimal-prefix: one of
|
/// hexadecimal-prefix: one of
|
||||||
/// 0x 0X
|
/// 0x 0X
|
||||||
|
/// binary-literal:
|
||||||
|
/// 0b binary-digit
|
||||||
|
/// 0B binary-digit
|
||||||
|
/// binary-literal binary-digit
|
||||||
/// integer-suffix:
|
/// integer-suffix:
|
||||||
/// unsigned-suffix [long-suffix]
|
/// unsigned-suffix [long-suffix]
|
||||||
/// unsigned-suffix [long-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
|
/// 0 1 2 3 4 5 6 7 8 9
|
||||||
/// a b c d e f
|
/// a b c d e f
|
||||||
/// A B C D E F
|
/// A B C D E F
|
||||||
|
/// binary-digit:
|
||||||
|
/// 0
|
||||||
|
/// 1
|
||||||
/// unsigned-suffix: one of
|
/// unsigned-suffix: one of
|
||||||
/// u U
|
/// u U
|
||||||
/// long-suffix: one of
|
/// 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
|
// Parse the suffix. At this point we can classify whether we have an FP or
|
||||||
// integer constant.
|
// integer constant.
|
||||||
bool isFPConstant = isFloatingLiteral();
|
bool isFPConstant = isFloatingLiteral();
|
||||||
|
const char *ImaginarySuffixLoc = 0;
|
||||||
|
|
||||||
// Loop over all of the characters of the suffix. If we see something bad,
|
// Loop over all of the characters of the suffix. If we see something bad,
|
||||||
// we break out of the loop.
|
// we break out of the loop.
|
||||||
|
@ -598,9 +608,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
|
||||||
case 'j':
|
case 'j':
|
||||||
case 'J':
|
case 'J':
|
||||||
if (isImaginary) break; // Cannot be repeated.
|
if (isImaginary) break; // Cannot be repeated.
|
||||||
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
|
|
||||||
diag::ext_imaginary_constant);
|
|
||||||
isImaginary = true;
|
isImaginary = true;
|
||||||
|
ImaginarySuffixLoc = s;
|
||||||
continue; // Success.
|
continue; // Success.
|
||||||
}
|
}
|
||||||
// If we reached here, there was an error or a ud-suffix.
|
// If we reached here, there was an error or a ud-suffix.
|
||||||
|
@ -608,9 +617,17 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s != ThisTokEnd) {
|
if (s != ThisTokEnd) {
|
||||||
if (PP.getLangOpts().CPlusPlus11 && s == SuffixBegin && *s == '_') {
|
if (isValidUDSuffix(PP.getLangOpts(),
|
||||||
// We have a ud-suffix! By C++11 [lex.ext]p10, ud-suffixes not starting
|
StringRef(SuffixBegin, ThisTokEnd - SuffixBegin))) {
|
||||||
// with an '_' are ill-formed.
|
// 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;
|
saw_ud_suffix = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -623,6 +640,35 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
|
||||||
hadError = true;
|
hadError = true;
|
||||||
return;
|
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
|
/// ParseNumberStartingWithZero - This method is called when the first character
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "clang/AST/TypeOrdering.h"
|
#include "clang/AST/TypeOrdering.h"
|
||||||
#include "clang/Basic/PartialDiagnostic.h"
|
#include "clang/Basic/PartialDiagnostic.h"
|
||||||
#include "clang/Basic/TargetInfo.h"
|
#include "clang/Basic/TargetInfo.h"
|
||||||
|
#include "clang/Lex/LiteralSupport.h"
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include "clang/Lex/Preprocessor.h"
|
||||||
#include "clang/Sema/CXXFieldCollector.h"
|
#include "clang/Sema/CXXFieldCollector.h"
|
||||||
#include "clang/Sema/DeclSpec.h"
|
#include "clang/Sema/DeclSpec.h"
|
||||||
|
@ -10650,7 +10651,8 @@ FinishedParams:
|
||||||
// C++11 [usrlit.suffix]p1:
|
// C++11 [usrlit.suffix]p1:
|
||||||
// Literal suffix identifiers that do not start with an underscore
|
// Literal suffix identifiers that do not start with an underscore
|
||||||
// are reserved for future standardization.
|
// 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;
|
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