<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 23 May 2017 at 14:41, Tim Northover via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: tnorthover<br>
Date: Tue May 23 16:41:49 2017<br>
New Revision: 303694<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=303694&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=303694&view=rev</a><br>
Log:<br>
Sema: allow imaginary constants via GNU extension if UDL overloads not present.<br>
<br>
C++14 added user-defined literal support for complex numbers so that you can<br>
write something like "complex<double> val = 2i". However, there is an existing<br>
GNU extension supporting this syntax and interpreting the result as a _Complex<br>
type.<br>
<br>
This changes parsing so that such literals are interpreted in terms of C++14's<br>
operators if an overload is present but otherwise falls back to the original<br>
GNU extension.<br>
<br>
Added:<br>
    cfe/trunk/test/SemaCXX/<wbr>imaginary-constants.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/<wbr>DiagnosticLexKinds.td<br>
    cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
    cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
    cfe/trunk/lib/Lex/<wbr>LiteralSupport.cpp<br>
    cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp<br>
    cfe/trunk/lib/Sema/SemaLookup.<wbr>cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticLexKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=303694&r1=303693&r2=303694&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/<wbr>DiagnosticLexKinds.td?rev=<wbr>303694&r1=303693&r2=303694&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticLexKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticLexKinds.td Tue May 23 16:41:49 2017<br>
@@ -173,8 +173,6 @@ def warn_char_constant_too_large : Warni<br>
 def err_multichar_utf_character_<wbr>literal : Error<<br>
   "Unicode character literals may not contain multiple characters">;<br>
 def err_exponent_has_no_digits : Error<"exponent has no digits">;<br>
-def ext_imaginary_constant : Extension<<br>
-  "imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>;<br>
 def err_hex_constant_requires : Error<<br>
   "hexadecimal floating %select{constant|literal}0 requires "<br>
   "%select{an exponent|a significand}1">;<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=303694&r1=303693&r2=303694&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/<wbr>DiagnosticSemaKinds.td?rev=<wbr>303694&r1=303693&r2=303694&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td Tue May 23 16:41:49 2017<br>
@@ -194,6 +194,8 @@ def warn_duplicate_declspec : Warning<"d<br>
   InGroup<<wbr>DuplicateDeclSpecifier>;<br>
 def ext_plain_complex : ExtWarn<<br>
   "plain '_Complex' requires a type specifier; assuming '_Complex double'">;<br>
+def ext_imaginary_constant : Extension<<br>
+  "imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>;<br>
 def ext_integer_complex : Extension<<br>
   "complex integer types are a GNU extension">, InGroup<GNUComplexInteger>;<br>
<br>
<br>
Modified: cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=303694&r1=303693&r2=303694&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Sema/Sema.h?rev=303694&<wbr>r1=303693&r2=303694&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Sema/<wbr>Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/<wbr>Sema.h Tue May 23 16:41:49 2017<br>
@@ -2946,6 +2946,8 @@ public:<br>
   enum LiteralOperatorLookupResult {<br>
     /// \brief The lookup resulted in an error.<br>
     LOLR_Error,<br>
+    /// \brief The lookup found no match but no diagnostic was issued.<br>
+    LOLR_ErrorNoDiagnostic,<br>
     /// \brief The lookup found a single 'cooked' literal operator, which<br>
     /// expects a normal literal to be built and passed to it.<br>
     LOLR_Cooked,<br>
@@ -3070,7 +3072,8 @@ public:<br>
                                                     ArrayRef<QualType> ArgTys,<br>
                                                     bool AllowRaw,<br>
                                                     bool AllowTemplate,<br>
-                                                    bool AllowStringTemplate);<br>
+                                                    bool AllowStringTemplate,<br>
+                                                    bool DiagnoseMissing);<br>
   bool isKnownName(StringRef name);<br>
<br>
   void ArgumentDependentLookup(<wbr>DeclarationName Name, SourceLocation Loc,<br>
<br>
Modified: cfe/trunk/lib/Lex/<wbr>LiteralSupport.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/LiteralSupport.cpp?rev=303694&r1=303693&r2=303694&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Lex/<wbr>LiteralSupport.cpp?rev=303694&<wbr>r1=303693&r2=303694&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Lex/<wbr>LiteralSupport.cpp (original)<br>
+++ cfe/trunk/lib/Lex/<wbr>LiteralSupport.cpp Tue May 23 16:41:49 2017<br>
@@ -652,9 +652,6 @@ NumericLiteralParser::<wbr>NumericLiteralPars<br>
           break;<br>
         }<br>
       }<br>
-      // "i", "if", and "il" are user-defined suffixes in C++1y.<br>
-      if (*s == 'i' && PP.getLangOpts().CPlusPlus14)<br>
-        break;<br>
       // fall through.<br>
     case 'j':<br>
     case 'J':<br>
@@ -667,36 +664,34 @@ NumericLiteralParser::<wbr>NumericLiteralPars<br>
     break;<br>
   }<br>
<br>
-  if (s != ThisTokEnd) {<br>
+  // "i", "if", and "il" are user-defined suffixes in C++1y.<br>
+  if (s != ThisTokEnd || isImaginary) {<br>
     // FIXME: Don't bother expanding UCNs if !tok.hasUCN().<br>
     expandUCNs(UDSuffixBuf, StringRef(SuffixBegin, ThisTokEnd - SuffixBegin));<br>
     if (isValidUDSuffix(PP.<wbr>getLangOpts(), UDSuffixBuf)) {<br>
-      // Any suffix pieces we might have parsed are actually part of the<br>
-      // ud-suffix.<br>
-      isLong = false;<br>
-      isUnsigned = false;<br>
-      isLongLong = false;<br>
-      isFloat = false;<br>
-      isHalf = false;<br>
-      isImaginary = false;<br>
-      MicrosoftInteger = 0;<br>
+      if (!isImaginary) {<br></blockquote><div><br></div><div>Shouldn't this be "if (s != ThisTokEnd)"? (That is, if this was not a valid builtin suffix, reset the suffix information.)</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+        // Any suffix pieces we might have parsed are actually part of the<br>
+        // ud-suffix.<br>
+        isLong = false;<br>
+        isUnsigned = false;<br>
+        isLongLong = false;<br>
+        isFloat = false;<br>
+        isHalf = false;<br>
+        isImaginary = false;<br>
+        MicrosoftInteger = 0;<br>
+      }<br>
<br>
       saw_ud_suffix = true;<br>
       return;<br>
     }<br>
<br>
-    // Report an error if there are any.<br>
-    PP.Diag(PP.<wbr>AdvanceToTokenCharacter(<wbr>TokLoc, SuffixBegin - ThisTokBegin),<br>
-            diag::err_invalid_suffix_<wbr>constant)<br>
-      << StringRef(SuffixBegin, ThisTokEnd-SuffixBegin) << isFPConstant;<br>
-    hadError = true;<br>
-    return;<br>
-  }<br>
-<br>
-  if (isImaginary) {<br>
-    PP.Diag(PP.<wbr>AdvanceToTokenCharacter(<wbr>TokLoc,<br>
-                                       ImaginarySuffixLoc - ThisTokBegin),<br>
-            diag::ext_imaginary_constant);<br>
+    if (s != ThisTokEnd) {<br>
+      // Report an error if there are any.<br>
+      PP.Diag(PP.<wbr>AdvanceToTokenCharacter(<wbr>TokLoc, SuffixBegin - ThisTokBegin),<br>
+              diag::err_invalid_suffix_<wbr>constant)<br>
+          << StringRef(SuffixBegin, ThisTokEnd - SuffixBegin) << isFPConstant;<br>
+      hadError = true;<br>
+    }<br>
   }<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=303694&r1=303693&r2=303694&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaExpr.cpp?rev=303694&r1=<wbr>303693&r2=303694&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp Tue May 23 16:41:49 2017<br>
@@ -1599,8 +1599,9 @@ static ExprResult BuildCookedLiteralOper<br>
<br>
   LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName);<br>
   if (S.LookupLiteralOperator(<wbr>Scope, R, llvm::makeArrayRef(ArgTy, Args.size()),<br>
-                              /*AllowRaw*/false, /*AllowTemplate*/false,<br>
-                              /*AllowStringTemplate*/false) == Sema::LOLR_Error)<br>
+                              /*AllowRaw*/ false, /*AllowTemplate*/ false,<br>
+                              /*AllowStringTemplate*/ false,<br>
+                              /*DiagnoseMissing*/ true) == Sema::LOLR_Error)<br>
     return ExprError();<br>
<br>
   return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc);<br>
@@ -1691,8 +1692,9 @@ Sema::ActOnStringLiteral(<wbr>ArrayRef<Token><br>
<br>
   LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);<br>
   switch (LookupLiteralOperator(<wbr>UDLScope, R, ArgTy,<br>
-                                /*AllowRaw*/false, /*AllowTemplate*/false,<br>
-                                /*AllowStringTemplate*/true)) {<br>
+                                /*AllowRaw*/ false, /*AllowTemplate*/ false,<br>
+                                /*AllowStringTemplate*/ true,<br>
+                                /*DiagnoseMissing*/ true)) {<br>
<br>
   case LOLR_Cooked: {<br>
     llvm::APInt Len(Context.getIntWidth(<wbr>SizeType), Literal.GetNumStringChars());<br>
@@ -1725,6 +1727,7 @@ Sema::ActOnStringLiteral(<wbr>ArrayRef<Token><br>
   }<br>
   case LOLR_Raw:<br>
   case LOLR_Template:<br>
+  case LOLR_ErrorNoDiagnostic:<br>
     llvm_unreachable("unexpected literal operator lookup result");<br>
   case LOLR_Error:<br>
     return ExprError();<br>
@@ -3347,11 +3350,15 @@ ExprResult Sema::ActOnNumericConstant(co<br>
     // literal or a cooked one.<br>
     LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);<br>
     switch (LookupLiteralOperator(<wbr>UDLScope, R, CookedTy,<br>
-                                  /*AllowRaw*/true, /*AllowTemplate*/true,<br>
-                                  /*AllowStringTemplate*/false)) {<br>
+                                  /*AllowRaw*/ true, /*AllowTemplate*/ true,<br>
+                                  /*AllowStringTemplate*/ false,<br>
+                                  /*DiagnoseMissing*/ !Literal.isImaginary)) {<br>
+    case LOLR_ErrorNoDiagnostic:<br>
+      // Lookup failure for imaginary constants isn't fatal, there's still the<br>
+      // GNU extension producing _Complex types.<br>
+      break;<br>
     case LOLR_Error:<br>
       return ExprError();<br>
-<br>
     case LOLR_Cooked: {<br>
       Expr *Lit;<br>
       if (Literal.isFloatingLiteral()) {<br>
@@ -3567,10 +3574,12 @@ ExprResult Sema::ActOnNumericConstant(co<br>
   }<br>
<br>
   // If this is an imaginary literal, create the ImaginaryLiteral wrapper.<br>
-  if (Literal.isImaginary)<br>
+  if (Literal.isImaginary) {<br>
     Res = new (Context) ImaginaryLiteral(Res,<br>
                                         Context.getComplexType(Res-><wbr>getType()));<br>
<br>
+    Diag(Tok.getLocation(), diag::ext_imaginary_constant);<br>
+  }<br>
   return Res;<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaLookup.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=303694&r1=303693&r2=303694&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaLookup.cpp?rev=303694&r1=<wbr>303693&r2=303694&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaLookup.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaLookup.<wbr>cpp Tue May 23 16:41:49 2017<br>
@@ -3066,7 +3066,7 @@ Sema::<wbr>LiteralOperatorLookupResult<br>
 Sema::LookupLiteralOperator(<wbr>Scope *S, LookupResult &R,<br>
                             ArrayRef<QualType> ArgTys,<br>
                             bool AllowRaw, bool AllowTemplate,<br>
-                            bool AllowStringTemplate) {<br>
+                            bool AllowStringTemplate, bool DiagnoseMissing) {<br>
   LookupName(R, S);<br>
   assert(R.getResultKind() != LookupResult::Ambiguous &&<br>
          "literal operator lookup can't be ambiguous");<br>
@@ -3167,11 +3167,15 @@ Sema::LookupLiteralOperator(<wbr>Scope *S, Lo<br>
     return LOLR_StringTemplate;<br>
<br>
   // Didn't find anything we could use.<br>
-  Diag(R.getNameLoc(), diag::err_ovl_no_viable_<wbr>literal_operator)<br>
-    << R.getLookupName() << (int)ArgTys.size() << ArgTys[0]<br>
-    << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw<br>
-    << (AllowTemplate || AllowStringTemplate);<br>
-  return LOLR_Error;<br>
+  if (DiagnoseMissing) {<br>
+    Diag(R.getNameLoc(), diag::err_ovl_no_viable_<wbr>literal_operator)<br>
+        << R.getLookupName() << (int)ArgTys.size() << ArgTys[0]<br>
+        << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw<br>
+        << (AllowTemplate || AllowStringTemplate);<br>
+    return LOLR_Error;<br>
+  }<br>
+<br>
+  return LOLR_ErrorNoDiagnostic;<br>
 }<br>
<br>
 void ADLResult::insert(NamedDecl *New) {<br>
<br>
Added: cfe/trunk/test/SemaCXX/<wbr>imaginary-constants.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/imaginary-constants.cpp?rev=303694&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaCXX/imaginary-constants.<wbr>cpp?rev=303694&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/SemaCXX/<wbr>imaginary-constants.cpp (added)<br>
+++ cfe/trunk/test/SemaCXX/<wbr>imaginary-constants.cpp Tue May 23 16:41:49 2017<br>
@@ -0,0 +1,44 @@<br>
+// RUN: %clang_cc1 -fsyntax-only -verify %s -include %s -std=gnu++98<br>
+// RUN: %clang_cc1 -fsyntax-only -verify %s -include %s -std=c++11<br>
+// RUN: %clang_cc1 -fsyntax-only -verify %s -include %s -std=c++14 -DCXX14=1<br>
+<br>
+// expected-no-diagnostics<br>
+<br>
+#ifndef HEADER<br>
+#define HEADER<br>
+<br>
+_Complex int val1 = 2i;<br>
+_Complex long val2 = 2il;<br>
+_Complex long long val3 = 2ill;<br>
+_Complex float val4 = 2.0if;<br>
+_Complex double val5 = 2.0i;<br>
+_Complex long double val6 = 2.0il;<br>
+<br>
+#if CXX14<br>
+<br>
+#pragma clang system_header<br>
+<br>
+namespace std {<br>
+  template<typename T> struct complex {};<br>
+  complex<float> operator""if(unsigned long long);<br>
+  complex<float> operator""if(long double);<br>
+<br>
+  complex<double> operator"" i(unsigned long long);<br>
+  complex<double> operator"" i(long double);<br>
+<br>
+  complex<long double> operator"" il(unsigned long long);<br>
+  complex<long double> operator"" il(long double);<br>
+}<br>
+<br>
+using namespace std;<br>
+<br>
+complex<float> f1 = 2.0if;<br>
+complex<float> f2 = 2if;<br>
+complex<double> d1 = 2.0i;<br>
+complex<double> d2 = 2i;<br>
+complex<long double> l1 = 2.0il;<br>
+complex<long double> l2 = 2il;<br>
+<br>
+#endif<br>
+<br>
+#endif<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>