summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Lex/Lexer.cpp24
-rw-r--r--clang/lib/Lex/LiteralSupport.cpp56
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp4
3 files changed, 72 insertions, 12 deletions
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index 9505ccd9722..71db68a58c0 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -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,9 +1607,20 @@ 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(CurPtr, getLangOpts().MicrosoftMode ?
diag::ext_ms_reserved_user_defined_literal :
diag::ext_reserved_user_defined_literal)
<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
@@ -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())
diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp
index 84882d02165..7641bfaa8b2 100644
--- a/clang/lib/Lex/LiteralSupport.cpp
+++ b/clang/lib/Lex/LiteralSupport.cpp
@@ -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
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index b6f5fe9eb4f..015133041f9 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -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;
OpenPOWER on IntegriCloud