<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>