Index: include/clang/Lex/LiteralSupport.h =================================================================== --- include/clang/Lex/LiteralSupport.h +++ include/clang/Lex/LiteralSupport.h @@ -259,6 +259,8 @@ return UDSuffixOffset; } + static bool isValidUDSuffix(const LangOptions &LangOpts, StringRef Suffix); + private: void init(ArrayRef StringToks); bool CopyStringFragment(const Token &Tok, const char *TokBegin, Index: lib/Lex/Lexer.cpp =================================================================== --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -1713,9 +1713,9 @@ getLangOpts()); if (!isIdentifierBody(Next)) { // End of suffix. Check whether this is on the whitelist. - IsUDSuffix = (Chars == 1 && Buffer[0] == 's') || - NumericLiteralParser::isValidUDSuffix( - getLangOpts(), StringRef(Buffer, Chars)); + const StringRef CompleteSuffix(Buffer, Chars); + IsUDSuffix = StringLiteralParser::isValidUDSuffix(getLangOpts(), + CompleteSuffix); break; } Index: lib/Lex/LiteralSupport.cpp =================================================================== --- lib/Lex/LiteralSupport.cpp +++ lib/Lex/LiteralSupport.cpp @@ -1708,3 +1708,12 @@ return SpellingPtr-SpellingStart; } + +/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved +/// suffixes as ud-suffixes, because the diagnostic experience is better if we +/// treat it as an invalid suffix. +bool StringLiteralParser::isValidUDSuffix(const LangOptions &LangOpts, + StringRef Suffix) { + return NumericLiteralParser::isValidUDSuffix(LangOpts, Suffix) || + Suffix == "sv"; +} Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -12908,7 +12908,7 @@ // Literal suffix identifiers that do not start with an underscore // are reserved for future standardization. Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved) - << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName); + << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName); } return false; Index: test/SemaCXX/cxx1z-user-defined-literals.cpp =================================================================== --- test/SemaCXX/cxx1z-user-defined-literals.cpp +++ test/SemaCXX/cxx1z-user-defined-literals.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++1z %s -include %s -verify + +#ifndef INCLUDED +#define INCLUDED + +#pragma clang system_header +namespace std { + using size_t = decltype(sizeof(0)); + + struct string_view {}; + string_view operator""sv(const char*, size_t); +} + +#else + +using namespace std; +string_view s = "foo"sv; +const char* p = "bar"sv; // expected-error {{no viable conversion}} +char error = 'x'sv; // expected-error {{invalid suffix}} expected-error {{expected ';'}} + +#endif