rZhBoYao updated this revision to Diff 552060.
rZhBoYao marked 5 inline comments as done.
rZhBoYao edited the summary of this revision.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D158372/new/
https://reviews.llvm.org/D158372
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticLexKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/IdentifierTable.h
clang/lib/Lex/Lexer.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/CXX/drs/dr14xx.cpp
clang/test/CXX/drs/dr17xx.cpp
clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp
clang/test/FixIt/fixit-c++11.cpp
Index: clang/test/FixIt/fixit-c++11.cpp
===================================================================
--- clang/test/FixIt/fixit-c++11.cpp
+++ clang/test/FixIt/fixit-c++11.cpp
@@ -68,9 +68,9 @@
}
#define bar "bar"
-const char *p = "foo" bar;
+const char *p = "foo"bar; // expected-error {{requires a space between}}
#define ord - '0'
-int k = '4' ord;
+int k = '4'ord; // expected-error {{requires a space between}}
void operator"x" _y(char); // expected-error {{must be '""'}}
void operator L"" _z(char); // expected-error {{encoding prefix}}
Index: clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp
===================================================================
--- clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp
+++ clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -std=c++11 -verify %s
using size_t = decltype(sizeof(int));
-void operator ""wibble(const char *); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}}
-void operator ""wibble(const char *, size_t); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}}
+void operator ""wibble(const char *); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved}}
+void operator ""wibble(const char *, size_t); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved}}
template<typename T>
void f() {
Index: clang/test/CXX/drs/dr17xx.cpp
===================================================================
--- clang/test/CXX/drs/dr17xx.cpp
+++ clang/test/CXX/drs/dr17xx.cpp
@@ -141,9 +141,14 @@
namespace dr1762 { // dr1762: 14
// NB: reusing 1473 test
#if __cplusplus >= 201103L
- float operator ""_E(const char *);
- float operator ""E(const char *);
- // expected-warning@-1 {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}}
+#define E "!"
+const char
+ *operator""_E(const char*),
+ *operator""E(const char*), // don't err on the lack of spaces even when the literal suffix identifier is invalid
+ // expected-warning@-1 {{user-defined literal suffixes not starting with '_' are reserved}}
+ *s = "not empty"E;
+ // expected-error@-1 {{invalid suffix on literal; C++11 requires a space between literal and a macro}}
+#undef E
#endif
}
Index: clang/test/CXX/drs/dr14xx.cpp
===================================================================
--- clang/test/CXX/drs/dr14xx.cpp
+++ clang/test/CXX/drs/dr14xx.cpp
@@ -487,9 +487,14 @@
namespace dr1473 { // dr1473: 18
// NB: sup 1762, test reused there
#if __cplusplus >= 201103L
- float operator ""_E(const char *);
- float operator ""E(const char *); // don't err on the lack of spaces even when the literal suffix identifier is invalid
- // expected-warning@-1 {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}}
+#define E "!"
+const char
+ *operator""_E(const char*),
+ *operator""E(const char*), // don't err on the lack of spaces even when the literal suffix identifier is invalid
+ // expected-warning@-1 {{user-defined literal suffixes not starting with '_' are reserved}}
+ *s = "not empty"E;
+ // expected-error@-1 {{invalid suffix on literal; C++11 requires a space between literal and a macro}}
+#undef E
#endif
}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -16571,8 +16571,7 @@
// contain a double underscore __ are reserved for use by C++
// implementations.
Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
- << static_cast<int>(Status)
- << StringLiteralParser::isValidUDSuffix(getLangOpts(), II->getName());
+ << static_cast<int>(Status);
}
return false;
Index: clang/lib/Lex/Lexer.cpp
===================================================================
--- clang/lib/Lex/Lexer.cpp
+++ clang/lib/Lex/Lexer.cpp
@@ -1986,36 +1986,26 @@
assert(LangOpts.CPlusPlus);
// Maximally munch an identifier.
+ const char *const TokStart = CurPtr;
unsigned Size;
char C = getCharAndSize(CurPtr, Size);
- bool Consumed = false;
- if (!isAsciiIdentifierStart(C)) {
- if (C == '\\' && tryConsumeIdentifierUCN(CurPtr, Size, Result))
- Consumed = true;
- else if (!isASCII(C) && tryConsumeIdentifierUTF8Char(CurPtr))
- Consumed = true;
- else
- return CurPtr;
- }
+ if (isAsciiIdentifierStart(C)) {
+ CurPtr = ConsumeChar(CurPtr, Size, Result);
+ } else if (C == '\\' && tryConsumeIdentifierUCN(CurPtr, Size, Result)) {
+ } else if (!isASCII(C) && tryConsumeIdentifierUTF8Char(CurPtr)) {
+ } else
+ return CurPtr;
if (!LangOpts.CPlusPlus11) {
if (!isLexingRawMode())
- Diag(CurPtr,
+ Diag(TokStart,
C == '_' ? diag::warn_cxx11_compat_user_defined_literal
: diag::warn_cxx11_compat_reserved_user_defined_literal)
- << FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
- return CurPtr;
+ << FixItHint::CreateInsertion(getSourceLocation(TokStart), " ");
+ return TokStart;
}
- // C++11 [lex.ext]p10, [usrlit.suffix]p1: A program containing a ud-suffix
- // that does not start with an underscore is ill-formed. We assume a suffix
- // beginning with a UCN or UTF-8 character is more likely to be a ud-suffix
- // than a macro, however, and accept that.
- if (!Consumed)
- CurPtr = ConsumeChar(CurPtr, Size, Result);
-
- Result.setFlag(Token::HasUDSuffix);
while (true) {
C = getCharAndSize(CurPtr, Size);
if (isAsciiIdentifierContinue(C)) {
@@ -2026,6 +2016,31 @@
break;
}
+ bool IsLiteralOperator =
+ StringRef(BufferPtr, 2).equals("\"\"") && BufferPtr + 2 == TokStart;
+ if (unsigned TokLen = CurPtr - TokStart;
+ StringLiteralParser::isValidUDSuffix(LangOpts, {TokStart, TokLen}))
+ Result.setFlag(Token::HasUDSuffix);
+ else if (!isLexingRawMode() && !IsLiteralOperator) {
+ // As a conforming extension, we treat invalid suffixes as if they had
+ // whitespace before them if doing so results in macro expansions.
+ // However, don't diagnose operator""E(...) even if E is a macro as it
+ // results in confusing error messages. Hence, ""E would not be treated as
+ // string concat; instead it's a single PP token (as it should be).
+ Result.setLength(TokLen);
+ Result.setLocation(getSourceLocation(TokStart, TokLen));
+ Result.setKind(tok::raw_identifier);
+ Result.setRawIdentifierData(TokStart);
+ IdentifierInfo *II = PP->LookUpIdentifierInfo(Result);
+ if (II->hasMacroDefinition()) {
+ Diag(TokStart, LangOpts.MSVCCompat
+ ? diag::ext_ms_reserved_user_defined_literal
+ : diag::ext_reserved_user_defined_literal)
+ << FixItHint::CreateInsertion(getSourceLocation(TokStart), " ");
+ return TokStart;
+ }
+ }
+
return CurPtr;
}
Index: clang/include/clang/Basic/IdentifierTable.h
===================================================================
--- clang/include/clang/Basic/IdentifierTable.h
+++ clang/include/clang/Basic/IdentifierTable.h
@@ -51,9 +51,9 @@
};
enum class ReservedLiteralSuffixIdStatus {
- NotReserved = 0,
- NotStartsWithUnderscore,
+ NotStartsWithUnderscore = 0,
ContainsDoubleUnderscore,
+ NotReserved,
};
/// Determine whether an identifier is reserved for use as a name at global
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9319,8 +9319,7 @@
"string literal operator templates are a GNU extension">,
InGroup<GNUStringLiteralOperatorTemplate>;
def warn_user_literal_reserved : Warning<
- "user-defined literal suffixes %select{<ERROR>|not starting with '_'|containing '__'}0 are reserved"
- "%select{; no literal will invoke this operator|}1">,
+ "user-defined literal suffixes %select{not starting with '_'|containing '__'}0 are reserved">,
InGroup<UserDefinedLiterals>;
// C++ conversion functions
Index: clang/include/clang/Basic/DiagnosticLexKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticLexKinds.td
+++ clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -276,6 +276,12 @@
"identifier after literal will be treated as a reserved user-defined literal "
"suffix in C++11">,
InGroup<CXX11CompatReservedUserDefinedLiteral>, DefaultIgnore;
+def ext_reserved_user_defined_literal : ExtWarn<
+ "invalid suffix on literal; C++11 requires a space between literal and "
+ "a macro">, InGroup<ReservedUserDefinedLiteral>, DefaultError;
+def ext_ms_reserved_user_defined_literal : ExtWarn<
+ ext_reserved_user_defined_literal.Summary>,
+ InGroup<ReservedUserDefinedLiteral>;
def err_unsupported_string_concat : Error<
"unsupported non-standard concatenation of string literals">;
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -94,10 +94,21 @@
Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Implemented `CWG1473 <https://wg21.link/CWG1473>`_ which allows spaces after ``operator""``.
- Clang used to err on the lack of space when the literal suffix identifier was invalid in
- all the language modes, which contradicted the deprecation of the whitespaces.
- Also turn on ``-Wdeprecated-literal-operator`` by default in all the language modes.
+- Implemented `CWG1473 <https://wg21.link/CWG1473>`_ allowing lack of space after ``operator""``.
+ Clang used to err on the lack of space when the literal suffix identifier was invalid,
+ contradicting ``-Wdeprecated-literal-operator`` which is now default on.
+ Instead, Clang now emits error only if the invalid suffix looks like a macro and the preceding
+ string literal is not empty, and then treat the suffix as if it were preceded by whitespace.
+
+ .. code-block:: cpp
+
+ #define E "!"
+ const char
+ *operator""E(const char*),
+ // ""E is a single token as it should be pedantically
+ *s = "not empty"E;
+ // treated as if whitespace preceds E hence a string concat:
+ // = "not empty!"
C Language Changes
------------------
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits