]> granicus.if.org Git - clang/commitdiff
Enable C++2a Chrono Literals
authorErich Keane <erich.keane@intel.com>
Thu, 19 Jul 2018 13:36:57 +0000 (13:36 +0000)
committerErich Keane <erich.keane@intel.com>
Thu, 19 Jul 2018 13:36:57 +0000 (13:36 +0000)
C++2a via http://wg21.link/p0355 permits the library
literals of 'd' and 'y'. This patch enables them in the
Lexer so that they can be properly parsed.

Note that 'd' gets confused with the hex character, so
modifications to how octal, binary, and decimal numbers are
parsed were required. Since this is simply making previously
invalid code legal, this should be fine.

Hex still greedily parses the 'd' as a hexit, since it would
a: violate [lex.ext]p1
b: break existing code.

Differential Revision: https://reviews.llvm.org/D49504

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337454 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Lex/LiteralSupport.cpp
test/SemaCXX/cxx2a-user-defined-literals.cpp [new file with mode: 0644]

index e695b2ba376547b346c25966a11892d45708b900..966dafca27197c1d2670541f8259a97d258870d9 100644 (file)
@@ -751,7 +751,8 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){
 
   // If we have a hex digit other than 'e' (which denotes a FP exponent) then
   // the code is using an incorrect base.
-  if (isHexDigit(*s) && *s != 'e' && *s != 'E') {
+  if (isHexDigit(*s) && *s != 'e' && *s != 'E' &&
+      !isValidUDSuffix(PP.getLangOpts(), StringRef(s, ThisTokEnd - s))) {
     PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
             diag::err_invalid_digit) << StringRef(s, 1) << (radix == 8 ? 1 : 0);
     hadError = true;
@@ -804,12 +805,14 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts,
   if (!LangOpts.CPlusPlus14)
     return false;
 
-  // In C++1y, "s", "h", "min", "ms", "us", and "ns" are used in the library.
+  // In C++14, "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.
+  // In C++2a "d" and "y" are used in the library.
   return llvm::StringSwitch<bool>(Suffix)
       .Cases("h", "min", "s", true)
       .Cases("ms", "us", "ns", true)
       .Cases("il", "i", "if", true)
+      .Cases("d", "y", LangOpts.CPlusPlus2a)
       .Default(false);
 }
 
@@ -922,7 +925,9 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
     s = SkipBinaryDigits(s);
     if (s == ThisTokEnd) {
       // Done.
-    } else if (isHexDigit(*s)) {
+    } else if (isHexDigit(*s) &&
+               !isValidUDSuffix(PP.getLangOpts(),
+                                StringRef(s, ThisTokEnd - s))) {
       PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
               diag::err_invalid_digit) << StringRef(s, 1) << 2;
       hadError = true;
diff --git a/test/SemaCXX/cxx2a-user-defined-literals.cpp b/test/SemaCXX/cxx2a-user-defined-literals.cpp
new file mode 100644 (file)
index 0000000..d730eba
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++2a %s -include %s -verify
+
+#ifndef INCLUDED
+#define INCLUDED
+
+#pragma clang system_header
+namespace std {
+  namespace chrono {
+    struct day{};
+    struct year{};
+  }
+  constexpr chrono::day operator"" d(unsigned long long d) noexcept;
+  constexpr chrono::year operator"" y(unsigned long long y) noexcept;
+}
+
+#else
+
+using namespace std;
+chrono::day dec_d = 5d;
+chrono::day oct_d = 05d;
+chrono::day bin_d = 0b011d;
+// expected-error@+3{{no viable conversion from 'int' to 'chrono::day'}}
+// expected-note@9{{candidate constructor (the implicit copy constructor)}}
+// expected-note@9{{candidate constructor (the implicit move constructor)}}
+chrono::day hex_d = 0x44d;
+chrono::year y  = 10y;
+#endif