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