forked from OSchip/llvm-project
Add support for WG21 N3599 (literal operator template for strings) as a GNU
extension. The GCC folks have decided to support this even though the standard committee have not yet approved this feature. Patch by Hristo Venev! llvm-svn: 192128
This commit is contained in:
parent
d29406233b
commit
b8b41d3ea4
|
@ -59,6 +59,8 @@ def GNUConditionalOmittedOperand : DiagGroup<"gnu-conditional-omitted-operand">;
|
|||
def ConfigMacros : DiagGroup<"config-macros">;
|
||||
def : DiagGroup<"ctor-dtor-privacy">;
|
||||
def GNUDesignator : DiagGroup<"gnu-designator">;
|
||||
def GNUStringLiteralOperatorTemplate :
|
||||
DiagGroup<"gnu-string-literal-operator-template">;
|
||||
|
||||
def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">;
|
||||
def AbstractFinalClass : DiagGroup<"abstract-final-class">;
|
||||
|
@ -561,6 +563,7 @@ def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
|
|||
GNUImaginaryConstant, GNULabelsAsValue,
|
||||
RedeclaredClassMember, GNURedeclaredEnum,
|
||||
GNUStatementExpression, GNUStaticFloatInit,
|
||||
GNUStringLiteralOperatorTemplate,
|
||||
GNUUnionCast, GNUVariableSizedTypeNotAtEnd,
|
||||
ZeroLengthArray, GNUZeroLineDirective,
|
||||
GNUZeroVariadicMacroArguments]>;
|
||||
|
|
|
@ -2811,7 +2811,8 @@ def err_addr_ovl_no_qualifier : Error<
|
|||
def err_ovl_no_viable_literal_operator : Error<
|
||||
"no matching literal operator for call to %0"
|
||||
"%select{| with argument of type %2| with arguments of types %2 and %3}1"
|
||||
"%select{| or 'const char *', and no matching literal operator template}4">;
|
||||
"%select{| or 'const char *'}4"
|
||||
"%select{|, and no matching literal operator template}5">;
|
||||
|
||||
// C++ Template Declarations
|
||||
def err_template_param_shadow : Error<
|
||||
|
@ -5913,6 +5914,9 @@ def err_literal_operator_params : Error<
|
|||
"parameter declaration for literal operator %0 is not valid">;
|
||||
def err_literal_operator_extern_c : Error<
|
||||
"literal operator must have C++ linkage">;
|
||||
def ext_string_literal_operator_template : ExtWarn<
|
||||
"string literal operator templates are a GNU extension">,
|
||||
InGroup<GNUStringLiteralOperatorTemplate>;
|
||||
def warn_user_literal_reserved : Warning<
|
||||
"user-defined literal suffixes not starting with '_' are reserved"
|
||||
"%select{; no literal will invoke this operator|}0">,
|
||||
|
|
|
@ -2400,7 +2400,11 @@ public:
|
|||
/// \brief The lookup found an overload set of literal operator templates,
|
||||
/// which expect the characters of the spelling of the literal token to be
|
||||
/// passed as a non-type template argument pack.
|
||||
LOLR_Template
|
||||
LOLR_Template,
|
||||
/// \brief The lookup found an overload set of literal operator templates,
|
||||
/// which expect the character type and characters of the spelling of the
|
||||
/// string literal token to be passed as template arguments.
|
||||
LOLR_StringTemplate
|
||||
};
|
||||
|
||||
SpecialMemberOverloadResult *LookupSpecialMember(CXXRecordDecl *D,
|
||||
|
@ -2467,7 +2471,9 @@ public:
|
|||
|
||||
LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R,
|
||||
ArrayRef<QualType> ArgTys,
|
||||
bool AllowRawAndTemplate);
|
||||
bool AllowRaw,
|
||||
bool AllowTemplate,
|
||||
bool AllowStringTemplate);
|
||||
bool isKnownName(StringRef name);
|
||||
|
||||
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
|
||||
|
|
|
@ -10917,11 +10917,12 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
|
|||
if (!TpDecl)
|
||||
TpDecl = FnDecl->getPrimaryTemplate();
|
||||
|
||||
// template <char...> type operator "" name() is the only valid template
|
||||
// signature, and the only valid signature with no parameters.
|
||||
// template <char...> type operator "" name() and
|
||||
// template <class T, T...> type operator "" name() are the only valid
|
||||
// template signatures, and the only valid signatures with no parameters.
|
||||
if (TpDecl) {
|
||||
if (FnDecl->param_size() == 0) {
|
||||
// Must have only one template parameter
|
||||
// Must have one or two template parameters
|
||||
TemplateParameterList *Params = TpDecl->getTemplateParameters();
|
||||
if (Params->size() == 1) {
|
||||
NonTypeTemplateParmDecl *PmDecl =
|
||||
|
@ -10931,6 +10932,27 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
|
|||
if (PmDecl && PmDecl->isTemplateParameterPack() &&
|
||||
Context.hasSameType(PmDecl->getType(), Context.CharTy))
|
||||
Valid = true;
|
||||
} else if (Params->size() == 2) {
|
||||
TemplateTypeParmDecl *PmType =
|
||||
dyn_cast<TemplateTypeParmDecl>(Params->getParam(0));
|
||||
NonTypeTemplateParmDecl *PmArgs =
|
||||
dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(1));
|
||||
|
||||
// The second template parameter must be a parameter pack with the
|
||||
// first template parameter as its type.
|
||||
if (PmType && PmArgs &&
|
||||
!PmType->isTemplateParameterPack() &&
|
||||
PmArgs->isTemplateParameterPack()) {
|
||||
const TemplateTypeParmType *TArgs =
|
||||
PmArgs->getType()->getAs<TemplateTypeParmType>();
|
||||
if (TArgs && TArgs->getDepth() == PmType->getDepth() &&
|
||||
TArgs->getIndex() == PmType->getIndex()) {
|
||||
Valid = true;
|
||||
if (ActiveTemplateInstantiations.empty())
|
||||
Diag(FnDecl->getLocation(),
|
||||
diag::ext_string_literal_operator_template);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (FnDecl->param_size()) {
|
||||
|
|
|
@ -1461,7 +1461,8 @@ static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
|
|||
|
||||
LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName);
|
||||
if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()),
|
||||
/*AllowRawAndTemplate*/false) == Sema::LOLR_Error)
|
||||
/*AllowRaw*/false, /*AllowTemplate*/false,
|
||||
/*AllowStringTemplate*/false) == Sema::LOLR_Error)
|
||||
return ExprError();
|
||||
|
||||
return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc);
|
||||
|
@ -1486,36 +1487,34 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
|
|||
for (unsigned i = 0; i != NumStringToks; ++i)
|
||||
StringTokLocs.push_back(StringToks[i].getLocation());
|
||||
|
||||
QualType StrTy = Context.CharTy;
|
||||
if (Literal.isWide())
|
||||
StrTy = Context.getWideCharType();
|
||||
else if (Literal.isUTF16())
|
||||
StrTy = Context.Char16Ty;
|
||||
else if (Literal.isUTF32())
|
||||
StrTy = Context.Char32Ty;
|
||||
else if (Literal.isPascal())
|
||||
StrTy = Context.UnsignedCharTy;
|
||||
|
||||
QualType CharTy = Context.CharTy;
|
||||
StringLiteral::StringKind Kind = StringLiteral::Ascii;
|
||||
if (Literal.isWide())
|
||||
if (Literal.isWide()) {
|
||||
CharTy = Context.getWideCharType();
|
||||
Kind = StringLiteral::Wide;
|
||||
else if (Literal.isUTF8())
|
||||
} else if (Literal.isUTF8()) {
|
||||
Kind = StringLiteral::UTF8;
|
||||
else if (Literal.isUTF16())
|
||||
} else if (Literal.isUTF16()) {
|
||||
CharTy = Context.Char16Ty;
|
||||
Kind = StringLiteral::UTF16;
|
||||
else if (Literal.isUTF32())
|
||||
} else if (Literal.isUTF32()) {
|
||||
CharTy = Context.Char32Ty;
|
||||
Kind = StringLiteral::UTF32;
|
||||
} else if (Literal.isPascal()) {
|
||||
CharTy = Context.UnsignedCharTy;
|
||||
}
|
||||
|
||||
QualType CharTyConst = CharTy;
|
||||
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
|
||||
if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
|
||||
StrTy.addConst();
|
||||
CharTyConst.addConst();
|
||||
|
||||
// Get an array type for the string, according to C99 6.4.5. This includes
|
||||
// the nul terminator character as well as the string length for pascal
|
||||
// strings.
|
||||
StrTy = Context.getConstantArrayType(StrTy,
|
||||
QualType StrTy = Context.getConstantArrayType(CharTyConst,
|
||||
llvm::APInt(32, Literal.GetNumStringChars()+1),
|
||||
ArrayType::Normal, 0);
|
||||
ArrayType::Normal, 0);
|
||||
|
||||
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
|
||||
StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(),
|
||||
|
@ -1538,12 +1537,57 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
|
|||
// C++11 [lex.ext]p5: The literal L is treated as a call of the form
|
||||
// operator "" X (str, len)
|
||||
QualType SizeType = Context.getSizeType();
|
||||
llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
|
||||
IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
|
||||
StringTokLocs[0]);
|
||||
Expr *Args[] = { Lit, LenArg };
|
||||
return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc,
|
||||
Args, StringTokLocs.back());
|
||||
|
||||
DeclarationName OpName =
|
||||
Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
|
||||
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
|
||||
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
|
||||
|
||||
QualType ArgTy[] = {
|
||||
Context.getArrayDecayedType(StrTy), SizeType
|
||||
};
|
||||
|
||||
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
|
||||
switch (LookupLiteralOperator(UDLScope, R, ArgTy,
|
||||
/*AllowRaw*/false, /*AllowTemplate*/false,
|
||||
/*AllowStringTemplate*/true)) {
|
||||
|
||||
case LOLR_Cooked: {
|
||||
llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
|
||||
IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
|
||||
StringTokLocs[0]);
|
||||
Expr *Args[] = { Lit, LenArg };
|
||||
|
||||
return BuildLiteralOperatorCall(R, OpNameInfo, Args, StringTokLocs.back());
|
||||
}
|
||||
|
||||
case LOLR_StringTemplate: {
|
||||
TemplateArgumentListInfo ExplicitArgs;
|
||||
|
||||
unsigned CharBits = Context.getIntWidth(CharTy);
|
||||
bool CharIsUnsigned = CharTy->isUnsignedIntegerType();
|
||||
llvm::APSInt Value(CharBits, CharIsUnsigned);
|
||||
|
||||
TemplateArgument TypeArg(CharTy);
|
||||
TemplateArgumentLocInfo TypeArgInfo(Context.getTrivialTypeSourceInfo(CharTy));
|
||||
ExplicitArgs.addArgument(TemplateArgumentLoc(TypeArg, TypeArgInfo));
|
||||
|
||||
for (unsigned I = 0, N = Lit->getLength(); I != N; ++I) {
|
||||
Value = Lit->getCodeUnit(I);
|
||||
TemplateArgument Arg(Context, Value, CharTy);
|
||||
TemplateArgumentLocInfo ArgInfo;
|
||||
ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
|
||||
}
|
||||
return BuildLiteralOperatorCall(R, OpNameInfo, None, StringTokLocs.back(),
|
||||
&ExplicitArgs);
|
||||
}
|
||||
case LOLR_Raw:
|
||||
case LOLR_Template:
|
||||
llvm_unreachable("unexpected literal operator lookup result");
|
||||
case LOLR_Error:
|
||||
return ExprError();
|
||||
}
|
||||
llvm_unreachable("unexpected literal operator lookup result");
|
||||
}
|
||||
|
||||
ExprResult
|
||||
|
@ -2942,11 +2986,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
|
|||
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
|
||||
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
|
||||
|
||||
SourceLocation TokLoc = Tok.getLocation();
|
||||
|
||||
// Perform literal operator lookup to determine if we're building a raw
|
||||
// literal or a cooked one.
|
||||
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
|
||||
switch (LookupLiteralOperator(UDLScope, R, CookedTy,
|
||||
/*AllowRawAndTemplate*/true)) {
|
||||
/*AllowRaw*/true, /*AllowTemplate*/true,
|
||||
/*AllowStringTemplate*/false)) {
|
||||
case LOLR_Error:
|
||||
return ExprError();
|
||||
|
||||
|
@ -2961,15 +3008,13 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
|
|||
Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy,
|
||||
Tok.getLocation());
|
||||
}
|
||||
return BuildLiteralOperatorCall(R, OpNameInfo, Lit,
|
||||
Tok.getLocation());
|
||||
return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc);
|
||||
}
|
||||
|
||||
case LOLR_Raw: {
|
||||
// C++11 [lit.ext]p3, p4: If S contains a raw literal operator, the
|
||||
// literal is treated as a call of the form
|
||||
// operator "" X ("n")
|
||||
SourceLocation TokLoc = Tok.getLocation();
|
||||
unsigned Length = Literal.getUDSuffixOffset();
|
||||
QualType StrTy = Context.getConstantArrayType(
|
||||
Context.CharTy.withConst(), llvm::APInt(32, Length + 1),
|
||||
|
@ -2980,7 +3025,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
|
|||
return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc);
|
||||
}
|
||||
|
||||
case LOLR_Template:
|
||||
case LOLR_Template: {
|
||||
// C++11 [lit.ext]p3, p4: Otherwise (S contains a literal operator
|
||||
// template), L is treated as a call fo the form
|
||||
// operator "" X <'c1', 'c2', ... 'ck'>()
|
||||
|
@ -2995,11 +3040,12 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
|
|||
TemplateArgumentLocInfo ArgInfo;
|
||||
ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
|
||||
}
|
||||
return BuildLiteralOperatorCall(R, OpNameInfo, None, Tok.getLocation(),
|
||||
return BuildLiteralOperatorCall(R, OpNameInfo, None, TokLoc,
|
||||
&ExplicitArgs);
|
||||
}
|
||||
|
||||
llvm_unreachable("unexpected literal operator lookup result");
|
||||
case LOLR_StringTemplate:
|
||||
llvm_unreachable("unexpected literal operator lookup result");
|
||||
}
|
||||
}
|
||||
|
||||
Expr *Res;
|
||||
|
|
|
@ -2711,7 +2711,8 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {
|
|||
Sema::LiteralOperatorLookupResult
|
||||
Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
|
||||
ArrayRef<QualType> ArgTys,
|
||||
bool AllowRawAndTemplate) {
|
||||
bool AllowRaw, bool AllowTemplate,
|
||||
bool AllowStringTemplate) {
|
||||
LookupName(R, S);
|
||||
assert(R.getResultKind() != LookupResult::Ambiguous &&
|
||||
"literal operator lookup can't be ambiguous");
|
||||
|
@ -2719,8 +2720,9 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
|
|||
// Filter the lookup results appropriately.
|
||||
LookupResult::Filter F = R.makeFilter();
|
||||
|
||||
bool FoundTemplate = false;
|
||||
bool FoundRaw = false;
|
||||
bool FoundTemplate = false;
|
||||
bool FoundStringTemplate = false;
|
||||
bool FoundExactMatch = false;
|
||||
|
||||
while (F.hasNext()) {
|
||||
|
@ -2728,16 +2730,17 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
|
|||
if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
|
||||
D = USD->getTargetDecl();
|
||||
|
||||
bool IsTemplate = isa<FunctionTemplateDecl>(D);
|
||||
bool IsRaw = false;
|
||||
bool IsExactMatch = false;
|
||||
|
||||
// If the declaration we found is invalid, skip it.
|
||||
if (D->isInvalidDecl()) {
|
||||
F.erase();
|
||||
continue;
|
||||
}
|
||||
|
||||
bool IsRaw = false;
|
||||
bool IsTemplate = false;
|
||||
bool IsStringTemplate = false;
|
||||
bool IsExactMatch = false;
|
||||
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
if (FD->getNumParams() == 1 &&
|
||||
FD->getParamDecl(0)->getType()->getAs<PointerType>())
|
||||
|
@ -2753,19 +2756,31 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (FunctionTemplateDecl *FD = dyn_cast<FunctionTemplateDecl>(D)) {
|
||||
TemplateParameterList *Params = FD->getTemplateParameters();
|
||||
if (Params->size() == 1)
|
||||
IsTemplate = true;
|
||||
else
|
||||
IsStringTemplate = true;
|
||||
}
|
||||
|
||||
if (IsExactMatch) {
|
||||
FoundExactMatch = true;
|
||||
AllowRawAndTemplate = false;
|
||||
if (FoundRaw || FoundTemplate) {
|
||||
AllowRaw = false;
|
||||
AllowTemplate = false;
|
||||
AllowStringTemplate = false;
|
||||
if (FoundRaw || FoundTemplate || FoundStringTemplate) {
|
||||
// Go through again and remove the raw and template decls we've
|
||||
// already found.
|
||||
F.restart();
|
||||
FoundRaw = FoundTemplate = false;
|
||||
FoundRaw = FoundTemplate = FoundStringTemplate = false;
|
||||
}
|
||||
} else if (AllowRawAndTemplate && (IsTemplate || IsRaw)) {
|
||||
FoundTemplate |= IsTemplate;
|
||||
FoundRaw |= IsRaw;
|
||||
} else if (AllowRaw && IsRaw) {
|
||||
FoundRaw = true;
|
||||
} else if (AllowTemplate && IsTemplate) {
|
||||
FoundTemplate = true;
|
||||
} else if (AllowStringTemplate && IsStringTemplate) {
|
||||
FoundStringTemplate = true;
|
||||
} else {
|
||||
F.erase();
|
||||
}
|
||||
|
@ -2800,10 +2815,14 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
|
|||
if (FoundTemplate)
|
||||
return LOLR_Template;
|
||||
|
||||
if (FoundStringTemplate)
|
||||
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()) << AllowRawAndTemplate;
|
||||
<< (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw
|
||||
<< (AllowTemplate || AllowStringTemplate);
|
||||
return LOLR_Error;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
|
||||
|
||||
using size_t = decltype(sizeof(int));
|
||||
|
||||
template<typename T, typename U> struct same_type;
|
||||
template<typename T> struct same_type<T, T> {};
|
||||
template<typename T> using X = T;
|
||||
template<typename CharT, X<CharT>...>
|
||||
int operator "" _x(); // expected-warning {{string literal operator templates are a GNU extension}}
|
||||
template<char...>
|
||||
double operator "" _x();
|
||||
|
||||
auto a="string"_x;
|
||||
auto b=42_x;
|
||||
same_type<decltype(a), int> test_a;
|
||||
same_type<decltype(b), double> test_b;
|
||||
|
||||
char operator "" _x(const char *begin, size_t size);
|
||||
auto c="string"_x;
|
||||
auto d=L"string"_x;
|
||||
same_type<decltype(c), char> test_c;
|
||||
same_type<decltype(d), int> test_d;
|
|
@ -0,0 +1,21 @@
|
|||
// RUN: %clang_cc1 -std=gnu++11 -verify %s
|
||||
|
||||
template<typename T, T... cs> struct check; // expected-note {{template is declared here}} expected-note {{template is declared here}}
|
||||
template<>
|
||||
struct check<char, 34, -47, -126, -48, -75, -47, -127, -47, -126, 32, -16, -112, -128, -128>{};
|
||||
template<>
|
||||
struct check<char16_t, 34, 1090, 1077, 1089, 1090, 32, 55296, 56320>{};
|
||||
template<>
|
||||
struct check<char32_t, 34, 1090, 1077, 1089, 1090, 32, 65536>{};
|
||||
template<typename T, T... str> int operator""_x() { // #1 expected-warning {{string literal operator templates are a GNU extension}}
|
||||
check<T, str...> chars; // expected-error {{implicit instantiation of undefined template 'check<char, 't', 'e', 's', 't'>'}} expected-error {{implicit instantiation of undefined template 'check<char32_t, 34, 1090, 1077, 1089, 1090, 95, 65536>'}}
|
||||
return 1;
|
||||
}
|
||||
void *operator""_x(const char*); // #2
|
||||
void *a = 123_x; // ok, calls #2
|
||||
int b = u8"\"тест 𐀀"_x; // ok, calls #1
|
||||
int c = u8R"("тест 𐀀)"_x; // ok, calls #1
|
||||
int d = "test"_x; // expected-note {{in instantiation of function template specialization 'operator "" _x<char, 't', 'e', 's', 't'>' requested here}}
|
||||
int e = uR"("тест 𐀀)"_x;
|
||||
int f = UR"("тест 𐀀)"_x;
|
||||
int g = UR"("тест_𐀀)"_x; // expected-note {{in instantiation of function template specialization 'operator "" _x<char32_t, 34, 1090, 1077, 1089, 1090, 95, 65536>' requested here}}
|
|
@ -6,7 +6,7 @@ int &operator "" _x1 (const char *);
|
|||
double &operator "" _x1 (const char *, size_t);
|
||||
double &i1 = "foo"_x1;
|
||||
double &i2 = u8"foo"_x1;
|
||||
double &i3 = L"foo"_x1; // expected-error {{no matching literal operator}}
|
||||
double &i3 = L"foo"_x1; // expected-error {{no matching literal operator for call to 'operator "" _x1' with arguments of types 'const wchar_t *' and 'unsigned long'}}
|
||||
|
||||
char &operator "" _x1(const wchar_t *, size_t);
|
||||
char &i4 = L"foo"_x1; // ok
|
||||
|
|
|
@ -17,7 +17,7 @@ int main() {
|
|||
auto v1 = 1.2_w; // calls operator "" _w(1.2L)
|
||||
auto v2 = u"one"_w; // calls operator "" _w(u"one", 3)
|
||||
auto v3 = 12_w; // calls operator "" _w("12")
|
||||
"two"_w; // expected-error {{no matching literal operator}}
|
||||
"two"_w; // expected-error {{no matching literal operator for call to 'operator "" _w' with arguments of types 'const char *' and 'unsigned long'}}
|
||||
|
||||
same_type<decltype(v1), long double> test1;
|
||||
same_type<decltype(v2), std::string> test2;
|
||||
|
|
Loading…
Reference in New Issue