From 2a98862be2ed03a418e5d684636d527bb2f2dc90 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 24 Sep 2013 04:06:10 +0000 Subject: [PATCH] Handle standard libraries that miss out the space when defining the standard literal operators. Also, for now, allow the proposed C++1y "il", "i", and "if" suffixes too. (Will revert the latter if LWG decides not to go ahead with that change after all.) llvm-svn: 191274 --- clang/lib/Lex/Lexer.cpp | 34 +++++++++++++++---- clang/lib/Lex/LiteralSupport.cpp | 5 +++ .../SemaCXX/cxx1y-user-defined-literals.cpp | 26 ++++++++++---- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index e6b6b1fe1c1c..d8a5160e95d5 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -29,6 +29,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/LexDiagnostic.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" @@ -1638,12 +1639,33 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr, 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; + else if (IsStringLiteral && getLangOpts().CPlusPlus1y) { + // In C++1y, we need to look ahead a few characters to see if this is a + // valid suffix for a string literal or a numeric literal (this could be + // the 'operator""if' defining a numeric literal operator). + const int MaxStandardSuffixLength = 3; + char Buffer[MaxStandardSuffixLength] = { C }; + unsigned Consumed = Size; + unsigned Chars = 1; + while (true) { + unsigned NextSize; + char Next = getCharAndSizeNoWarn(CurPtr + Consumed, NextSize, + getLangOpts()); + if (!isIdentifierBody(Next)) { + // End of suffix. Check whether this is on the whitelist. + IsUDSuffix = (Chars == 1 && Buffer[0] == 's') || + NumericLiteralParser::isValidUDSuffix( + getLangOpts(), StringRef(Buffer, Chars)); + break; + } + + if (Chars == MaxStandardSuffixLength) + // Too long: can't be a standard suffix. + break; + + Buffer[Chars++] = Next; + Consumed += NextSize; + } } if (!IsUDSuffix) { diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index c637c3881927..893141d59574 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -604,6 +604,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, break; } } + // "i", "if", and "il" are user-defined suffixes in C++1y. + if (PP.getLangOpts().CPlusPlus1y && *s == 'i') + break; // fall through. case 'j': case 'J': @@ -665,9 +668,11 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts, return false; // In C++1y, "s", "h", "min", "ms", "us", and "ns" are used in the library. + // Per tweaked N3660, "il", "i", and "if" are also used in the library. return llvm::StringSwitch(Suffix) .Cases("h", "min", "s", true) .Cases("ms", "us", "ns", true) + .Cases("il", "i", "if", true) .Default(false); } diff --git a/clang/test/SemaCXX/cxx1y-user-defined-literals.cpp b/clang/test/SemaCXX/cxx1y-user-defined-literals.cpp index 85abfb4fbf93..fa4ff03fad7f 100644 --- a/clang/test/SemaCXX/cxx1y-user-defined-literals.cpp +++ b/clang/test/SemaCXX/cxx1y-user-defined-literals.cpp @@ -8,15 +8,23 @@ 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); + 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); + string operator""s(const char*, size_t); + + template struct complex {}; + complex operator""if(long double); + complex operator""if(unsigned long long); + complex operator""i(long double); + complex operator""i(unsigned long long); + complex operator""il(long double); + complex operator""il(unsigned long long); } #else @@ -29,4 +37,8 @@ char error = 'x's; // expected-error {{invalid suffix}} expected-error {{expecte int _1z = 1z; // expected-error {{invalid suffix}} int _1b = 1b; // expected-error {{invalid digit}} +complex cf1 = 1if, cf2 = 2.if, cf3 = 0x3if; +complex cd1 = 1i, cd2 = 2.i, cd3 = 0b0110101i; +complex cld1 = 1il, cld2 = 2.il, cld3 = 0047il; + #endif