Author: rsmith Date: Thu Nov 30 17:07:10 2017 New Revision: 319509 URL: http://llvm.org/viewvc/llvm-project?rev=319509&view=rev Log: [c++2a] P0515R3: lexer support for new <=> token.
Added: cfe/trunk/test/Lexer/cxx2a-spaceship.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td cfe/trunk/include/clang/Basic/TokenKinds.def cfe/trunk/lib/Lex/Lexer.cpp cfe/trunk/lib/Lex/TokenConcatenation.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=319509&r1=319508&r2=319509&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Thu Nov 30 17:07:10 2017 @@ -31,6 +31,14 @@ def warn_cxx98_compat_less_colon_colon : "'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx17_compat_spaceship : Warning< + "'<=>' operator is incompatible with C++ standards before C++2a">, + InGroup<CXXPre2aCompat>, DefaultIgnore; +def warn_cxx2a_compat_spaceship : Warning< + "'<=>' is a single token in C++2a; " + "add a space to avoid a change in behavior">, + InGroup<CXX2aCompat>; + // Trigraphs. def trigraph_ignored : Warning<"trigraph ignored">, InGroup<Trigraphs>; def trigraph_ignored_block_comment : Warning< Modified: cfe/trunk/include/clang/Basic/TokenKinds.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=319509&r1=319508&r2=319509&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TokenKinds.def (original) +++ cfe/trunk/include/clang/Basic/TokenKinds.def Thu Nov 30 17:07:10 2017 @@ -194,6 +194,7 @@ PUNCTUATOR(less, "<") PUNCTUATOR(lessless, "<<") PUNCTUATOR(lessequal, "<=") PUNCTUATOR(lesslessequal, "<<=") +PUNCTUATOR(spaceship, "<=>") PUNCTUATOR(greater, ">") PUNCTUATOR(greatergreater, ">>") PUNCTUATOR(greaterequal, ">=") Modified: cfe/trunk/lib/Lex/Lexer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Lexer.cpp?rev=319509&r1=319508&r2=319509&view=diff ============================================================================== --- cfe/trunk/lib/Lex/Lexer.cpp (original) +++ cfe/trunk/lib/Lex/Lexer.cpp Thu Nov 30 17:07:10 2017 @@ -3522,6 +3522,24 @@ LexNextToken: Kind = tok::lessless; } } else if (Char == '=') { + char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2); + if (After == '>') { + if (getLangOpts().CPlusPlus2a) { + if (!isLexingRawMode()) + Diag(BufferPtr, diag::warn_cxx17_compat_spaceship); + CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result), + SizeTmp2, Result); + Kind = tok::spaceship; + break; + } + // Suggest adding a space between the '<=' and the '>' to avoid a + // change in semantics if this turns up in C++ <=17 mode. + if (getLangOpts().CPlusPlus && !isLexingRawMode()) { + Diag(BufferPtr, diag::warn_cxx2a_compat_spaceship) + << FixItHint::CreateInsertion( + getSourceLocation(CurPtr + SizeTmp, SizeTmp2), " "); + } + } CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::lessequal; } else if (LangOpts.Digraphs && Char == ':') { // '<:' -> '[' Modified: cfe/trunk/lib/Lex/TokenConcatenation.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/TokenConcatenation.cpp?rev=319509&r1=319508&r2=319509&view=diff ============================================================================== --- cfe/trunk/lib/Lex/TokenConcatenation.cpp (original) +++ cfe/trunk/lib/Lex/TokenConcatenation.cpp Thu Nov 30 17:07:10 2017 @@ -103,6 +103,10 @@ TokenConcatenation::TokenConcatenation(P if (PP.getLangOpts().CPlusPlus1z) TokenInfo[tok::utf8_char_constant] |= aci_custom; + // These tokens have custom code in C++2a mode. + if (PP.getLangOpts().CPlusPlus2a) + TokenInfo[tok::lessequal ] |= aci_custom_firstchar; + // These tokens change behavior if followed by an '='. TokenInfo[tok::amp ] |= aci_avoid_equal; // &= TokenInfo[tok::plus ] |= aci_avoid_equal; // += @@ -283,5 +287,7 @@ bool TokenConcatenation::AvoidConcat(con return FirstChar == '#' || FirstChar == '@' || FirstChar == '%'; case tok::arrow: // ->* return PP.getLangOpts().CPlusPlus && FirstChar == '*'; + case tok::lessequal: // <=> (C++2a) + return PP.getLangOpts().CPlusPlus2a && FirstChar == '>'; } } Added: cfe/trunk/test/Lexer/cxx2a-spaceship.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/cxx2a-spaceship.cpp?rev=319509&view=auto ============================================================================== --- cfe/trunk/test/Lexer/cxx2a-spaceship.cpp (added) +++ cfe/trunk/test/Lexer/cxx2a-spaceship.cpp Thu Nov 30 17:07:10 2017 @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -std=c++17 %s -verify +// RUN: %clang_cc1 -std=c++2a %s -verify +// RUN: %clang_cc1 -std=c++2a %s -verify -Wc++17-compat -DCOMPAT +// +// RUN: %clang_cc1 -std=c++17 %s -E -o - | FileCheck %s --check-prefix=CXX17 +// RUN: %clang_cc1 -std=c++2a %s -E -o - | FileCheck %s --check-prefix=CXX20 + +namespace N { + +struct A {}; +void operator<=(A, A); +#if __cplusplus > 201703L +void operator<=>(A, A); // expected-error {{}} +#ifdef COMPAT +// expected-warning@-2 {{'<=>' operator is incompatible with C++ standards before C++2a}} +#endif +#endif + +template<auto> struct X {}; +X<operator<=> +#if __cplusplus <= 201703L + // expected-warning@-2 {{'<=>' is a single token in C++2a; add a space to avoid a change in behavior}} +#else + > // expected-error@-4 {{}} +#endif +#ifdef COMPAT +// expected-warning@-7 {{'<=>' operator is incompatible with C++ standards before C++2a}} +#endif + x; +} + +// <=> can be formed by pasting other comparison operators. +#if __cplusplus > 201703L +#define STR(x) #x +#define STR_EXPANDED(x) STR(x) +#define PASTE(x, y) x ## y +constexpr char a[] = STR_EXPANDED(PASTE(<, =>)); +constexpr char b[] = STR_EXPANDED(PASTE(<=, >)); +static_assert(__builtin_strcmp(a, "<=>") == 0); +static_assert(__builtin_strcmp(b, "<=>") == 0); +#endif + +// -E must not accidentally form a <=> token. + +// CXX17: preprocess1: < => +// CXX17: preprocess2: <=> +// CXX17: preprocess3: < => +// CXX17: preprocess4: <=>= +// CXX17: preprocess5: <=>> +// CXX17: preprocess6: <=>>= +// CXX17: preprocess7: <=> +// CXX17: preprocess8: <=>= +// +// CXX20: preprocess1: < => +// CXX20: preprocess2: <= > +// CXX20: preprocess3: < => +// CXX20: preprocess4: <= >= +// CXX20: preprocess5: <= >> +// CXX20: preprocess6: <= >>= +// CXX20: preprocess7: <=> +// CXX20: preprocess8: <=>= + +#define ID(x) x +[[some_vendor::some_attribute( // expected-warning {{unknown attribute}} +preprocess1: ID(<)ID(=>), +preprocess2: ID(<=)ID(>), +preprocess3: ID(<)ID(=)ID(>), +preprocess4: ID(<=)ID(>=), +preprocess5: ID(<=)ID(>>), +preprocess6: ID(<=)ID(>>=), +preprocess7: ID(<=>) // expected-warning 0-1{{'<=>'}} +preprocess8: ID(<=>=) // expected-warning 0-1{{'<=>'}} +)]]; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits