From 98f76adf4e941738c0b9fe3b9965fa63603e9c89 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 11 Nov 2020 17:12:18 -0800 Subject: [PATCH] Add new 'preferred_name' attribute. This attribute permits a typedef to be associated with a class template specialization as a preferred way of naming that class template specialization. This permits us to specify that (for example) the preferred way to express 'std::basic_string' is as 'std::string'. The attribute is applied to the various class templates in libc++ that have corresponding well-known typedef names. Differential Revision: https://reviews.llvm.org/D91311 --- clang/include/clang/Basic/Attr.td | 13 +++ clang/include/clang/Basic/AttrDocs.td | 24 +++++ .../clang/Basic/DiagnosticSemaKinds.td | 3 + clang/lib/AST/TypePrinter.cpp | 11 ++- clang/lib/Sema/SemaDeclAttr.cpp | 40 ++++++++ clang/lib/Sema/SemaTemplate.cpp | 14 ++- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 35 ++++++- clang/test/SemaTemplate/attributes.cpp | 64 +++++++++++++ clang/utils/TableGen/ClangAttrEmitter.cpp | 19 +++- libcxx/include/__config | 6 ++ libcxx/include/iosfwd | 32 +++++++ libcxx/include/regex | 93 +++++++++++++------ libcxx/include/string | 29 ++++-- libcxx/include/string_view | 29 ++++-- 14 files changed, 353 insertions(+), 59 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 0212b60a2afe..123313079d28 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -126,6 +126,9 @@ def FunctionTmpl FunctionDecl::TK_FunctionTemplate}], "function templates">; +def ClassTmpl : SubsetSubjectgetDescribedClassTemplate()}], + "class templates">; + // FIXME: this hack is needed because DeclNodes.td defines the base Decl node // type to be a class, not a definition. This makes it impossible to create an // attribute subject which accepts a Decl. Normally, this is not a problem, @@ -2376,6 +2379,16 @@ def Pascal : DeclOrTypeAttr { let Documentation = [Undocumented]; } +def PreferredName : InheritableAttr { + let Spellings = [Clang<"preferred_name", /*AllowInC*/0>]; + let Subjects = SubjectList<[ClassTmpl]>; + let Args = [TypeArgument<"TypedefType">]; + let Documentation = [PreferredNameDocs]; + let InheritEvenIfAlreadyPresent = 1; + let MeaningfulToClassTemplateDefinition = 1; + let TemplateDependent = 1; +} + def PreserveMost : DeclOrTypeAttr { let Spellings = [Clang<"preserve_most">]; let Documentation = [PreserveMostDocs]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index bf985986e21b..a6f31e7e7f46 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4417,6 +4417,30 @@ the old mangled name and the new code will use the new mangled name with tags. }]; } +def PreferredNameDocs : Documentation { + let Category = DocCatDecl; + let Content = [{ +The ``preferred_name`` attribute can be applied to a class template, and +specifies a preferred way of naming a specialization of the template. The +preferred name will be used whenever the corresponding template specialization +would otherwise be printed in a diagnostic or similar context. + +The preferred name must be a typedef or type alias declaration that refers to a +specialization of the class template (not including any type qualifiers). In +general this requires the template to be declared at least twice. For example: + +.. code-block:: c++ + + template struct basic_string; + using string = basic_string; + using wstring = basic_string; + template struct [[clang::preferred_name(string), + clang::preferred_name(wstring)]] basic_string { + // ... + }; + }]; +} + def PreserveMostDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 01a521fc603e..e79d021c1c94 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3941,6 +3941,9 @@ def note_protocol_decl : Note< "protocol is declared here">; def note_protocol_decl_undefined : Note< "protocol %0 has no definition">; +def err_attribute_preferred_name_arg_invalid : Error< + "argument %0 to 'preferred_name' attribute is not a typedef for " + "a specialization of %1">; // objc_designated_initializer attribute diagnostics. def warn_objc_designated_init_missing_super_call : Warning< diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 721031932a4a..b42ffde4a069 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/PrettyPrinter.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" @@ -19,6 +19,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -1348,6 +1349,14 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { } void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) { + // Print the preferred name if we have one for this type. + for (const auto *PNA : T->getDecl()->specific_attrs()) { + if (declaresSameEntity(PNA->getTypedefType()->getAsCXXRecordDecl(), + T->getDecl())) + return printTypeSpec( + PNA->getTypedefType()->castAs()->getDecl(), OS); + } + printTag(T->getDecl(), OS); } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a3153979deff..11286dc3d33f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1380,6 +1380,43 @@ static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; } +static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) { + auto *RD = cast(D); + ClassTemplateDecl *CTD = RD->getDescribedClassTemplate(); + assert(CTD && "attribute does not appertain to this declaration"); + + ParsedType PT = AL.getTypeArg(); + TypeSourceInfo *TSI = nullptr; + QualType T = S.GetTypeFromParser(PT, &TSI); + if (!TSI) + TSI = S.Context.getTrivialTypeSourceInfo(T, AL.getLoc()); + + if (!T.hasQualifiers() && T->getAs()) { + // Find the template name, if this type names a template specialization. + const TemplateDecl *Template = nullptr; + if (const auto *CTSD = dyn_cast_or_null( + T->getAsCXXRecordDecl())) { + Template = CTSD->getSpecializedTemplate(); + } else if (const auto *TST = T->getAs()) { + while (TST && TST->isTypeAlias()) + TST = TST->getAliasedType()->getAs(); + if (TST) + Template = TST->getTemplateName().getAsTemplateDecl(); + } + + if (Template && declaresSameEntity(Template, CTD)) { + D->addAttr(::new (S.Context) PreferredNameAttr(S.Context, AL, TSI)); + return; + } + } + + S.Diag(AL.getLoc(), diag::err_attribute_preferred_name_arg_invalid) + << T << CTD; + if (const auto *TT = T->getAs()) + S.Diag(TT->getDecl()->getLocation(), diag::note_entity_declared_at) + << TT->getDecl(); +} + static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) { // The IBOutlet/IBOutletCollection attributes only apply to instance // variables or properties of Objective-C classes. The outlet must also @@ -7728,6 +7765,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Packed: handlePackedAttr(S, D, AL); break; + case ParsedAttr::AT_PreferredName: + handlePreferredName(S, D, AL); + break; case ParsedAttr::AT_Section: handleSectionAttr(S, D, AL); break; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 03715ef600bc..4176aa1f458f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3792,11 +3792,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); } - if (Decl->getSpecializationKind() == TSK_Undeclared) { - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(Converted); - InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(), - Decl); + if (Decl->getSpecializationKind() == TSK_Undeclared && + ClassTemplate->getTemplatedDecl()->hasAttrs()) { + InstantiatingTemplate Inst(*this, TemplateLoc, Decl); + if (!Inst.isInvalid()) { + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(Converted); + InstantiateAttrsForDecl(TemplateArgLists, + ClassTemplate->getTemplatedDecl(), Decl); + } } // Diagnose uses of this specialization. diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 6623e86765d1..9db4f23d7296 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -548,12 +548,40 @@ static void instantiateDependentAMDGPUWavesPerEUAttr( S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr); } +/// Determine whether the attribute A might be relevent to the declaration D. +/// If not, we can skip instantiating it. The attribute may or may not have +/// been instantiated yet. +static bool isRelevantAttr(Sema &S, const Decl *D, const Attr *A) { + // 'preferred_name' is only relevant to the matching specialization of the + // template. + if (const auto *PNA = dyn_cast(A)) { + QualType T = PNA->getTypedefType(); + const auto *RD = cast(D); + if (!T->isDependentType() && !RD->isDependentContext() && + !declaresSameEntity(T->getAsCXXRecordDecl(), RD)) + return false; + for (const auto *ExistingPNA : D->specific_attrs()) + if (S.Context.hasSameType(ExistingPNA->getTypedefType(), + PNA->getTypedefType())) + return false; + return true; + } + + return true; +} + void Sema::InstantiateAttrsForDecl( const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *OuterMostScope) { if (NamedDecl *ND = dyn_cast(New)) { + // FIXME: This function is called multiple times for the same template + // specialization. We should only instantiate attributes that were added + // since the previous instantiation. for (const auto *TmplAttr : Tmpl->attrs()) { + if (!isRelevantAttr(*this, New, TmplAttr)) + continue; + // FIXME: If any of the special case versions from InstantiateAttrs become // applicable to template declaration, we'll need to add them here. CXXThisScopeRAII ThisScope( @@ -562,7 +590,7 @@ void Sema::InstantiateAttrsForDecl( Attr *NewAttr = sema::instantiateTemplateAttributeForDecl( TmplAttr, Context, *this, TemplateArgs); - if (NewAttr) + if (NewAttr && isRelevantAttr(*this, New, NewAttr)) New->addAttr(NewAttr); } } @@ -587,6 +615,9 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *OuterMostScope) { for (const auto *TmplAttr : Tmpl->attrs()) { + if (!isRelevantAttr(*this, New, TmplAttr)) + continue; + // FIXME: This should be generalized to more than just the AlignedAttr. const AlignedAttr *Aligned = dyn_cast(TmplAttr); if (Aligned && Aligned->isAlignmentDependent()) { @@ -709,7 +740,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs); - if (NewAttr) + if (NewAttr && isRelevantAttr(*this, New, TmplAttr)) New->addAttr(NewAttr); } } diff --git a/clang/test/SemaTemplate/attributes.cpp b/clang/test/SemaTemplate/attributes.cpp index 7a04c4705bf2..3f52412a23ac 100644 --- a/clang/test/SemaTemplate/attributes.cpp +++ b/clang/test/SemaTemplate/attributes.cpp @@ -63,3 +63,67 @@ namespace PR9049 { // CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" template [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations(); void UseAnnotations() { HasAnnotations(); } + +namespace preferred_name { + int x [[clang::preferred_name("frank")]]; // expected-error {{expected a type}} + int y [[clang::preferred_name(int)]]; // expected-warning {{'preferred_name' attribute only applies to class templates}} + struct [[clang::preferred_name(int)]] A; // expected-warning {{'preferred_name' attribute only applies to class templates}} + template struct [[clang::preferred_name(int)]] B; // expected-error {{argument 'int' to 'preferred_name' attribute is not a typedef for a specialization of 'B'}} + template struct C; + using X = C; // expected-note {{'X' declared here}} + typedef C Y; + using Z = const C; // expected-note {{'Z' declared here}} + template struct [[clang::preferred_name(C)]] C; // expected-error {{argument 'C' to 'preferred_name' attribute is not a typedef for a specialization of 'C'}} + template struct [[clang::preferred_name(X), clang::preferred_name(Y)]] C; + template struct [[clang::preferred_name(const X)]] C; // expected-error {{argument 'const preferred_name::X'}} + template struct [[clang::preferred_name(Z)]] C; // expected-error {{argument 'preferred_name::Z' (aka 'const C')}} + template struct C {}; + + // CHECK: ClassTemplateDecl {{.*}} *cf1; + C *cf2; + + void f(C a, C b, C c) { + auto p = a; + auto q = b; + auto r = c; + p.f(); // expected-error {{no member named 'f' in 'preferred_name::X'}} + q.f(); // expected-error {{no member named 'f' in 'preferred_name::Y'}} + r.f(); // expected-error {{no member named 'f' in 'preferred_name::C'}} + } + + template struct D; + using DInt = D; + template struct __attribute__((__preferred_name__(DInt))) D {}; + template struct D; + int use_dint = D().get(); // expected-error {{no member named 'get' in 'preferred_name::DInt'}} + + template struct MemberTemplate { + template struct Iter; + using iterator = Iter; + using const_iterator = Iter; + template + struct [[clang::preferred_name(iterator), + clang::preferred_name(const_iterator)]] Iter {}; + }; + auto it = MemberTemplate::Iter(); + int n = it; // expected-error {{no viable conversion from 'preferred_name::MemberTemplate::const_iterator' to 'int'}} +} diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index ec109e134e20..a5a599e206d3 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1149,8 +1149,9 @@ namespace { << "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n"; OS << " ExprResult " << "Result = S.SubstExpr(" << "A->get" << getUpperName() << "(), TemplateArgs);\n"; - OS << " tempInst" << getUpperName() << " = " - << "Result.getAs();\n"; + OS << " if (Result.isInvalid())\n"; + OS << " return nullptr;\n"; + OS << " tempInst" << getUpperName() << " = Result.get();\n"; OS << " }\n"; } @@ -1202,7 +1203,9 @@ namespace { << "_end();\n"; OS << " for (; I != E; ++I, ++TI) {\n"; OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n"; - OS << " *TI = Result.getAs();\n"; + OS << " if (Result.isInvalid())\n"; + OS << " return nullptr;\n"; + OS << " *TI = Result.get();\n"; OS << " }\n"; OS << " }\n"; } @@ -1273,8 +1276,16 @@ namespace { OS << " return false;\n"; } + void writeTemplateInstantiation(raw_ostream &OS) const override { + OS << " " << getType() << " tempInst" << getUpperName() << " =\n"; + OS << " S.SubstType(A->get" << getUpperName() << "Loc(), " + << "TemplateArgs, A->getLoc(), A->getAttrName());\n"; + OS << " if (!tempInst" << getUpperName() << ")\n"; + OS << " return nullptr;\n"; + } + void writeTemplateInstantiationArgs(raw_ostream &OS) const override { - OS << "A->get" << getUpperName() << "Loc()"; + OS << "tempInst" << getUpperName(); } void writePCHWrite(raw_ostream &OS) const override { diff --git a/libcxx/include/__config b/libcxx/include/__config index d2fdf6785c7e..033cd8aea068 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1318,6 +1318,12 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container( #endif #endif // !defined(_LIBCPP_NODEBUG_TYPE) +#if __has_attribute(__preferred_name__) +#define _LIBCPP_PREFERRED_NAME(x) __attribute__((__preferred_name__(x))) +#else +#define _LIBCPP_PREFERRED_NAME(x) +#endif + #if defined(_LIBCPP_ABI_MICROSOFT) && \ (defined(_LIBCPP_COMPILER_MSVC) || __has_declspec_attribute(empty_bases)) # define _LIBCPP_DECLSPEC_EMPTY_BASES __declspec(empty_bases) diff --git a/libcxx/include/iosfwd b/libcxx/include/iosfwd index 070fbe8bfad8..0a0de99ff3a7 100644 --- a/libcxx/include/iosfwd +++ b/libcxx/include/iosfwd @@ -185,6 +185,36 @@ typedef basic_ifstream wifstream; typedef basic_ofstream wofstream; typedef basic_fstream wfstream; +template + class _LIBCPP_PREFERRED_NAME(ios) _LIBCPP_PREFERRED_NAME(wios) basic_ios; + +template + class _LIBCPP_PREFERRED_NAME(streambuf) _LIBCPP_PREFERRED_NAME(wstreambuf) basic_streambuf; +template + class _LIBCPP_PREFERRED_NAME(istream) _LIBCPP_PREFERRED_NAME(wistream) basic_istream; +template + class _LIBCPP_PREFERRED_NAME(ostream) _LIBCPP_PREFERRED_NAME(wostream) basic_ostream; +template + class _LIBCPP_PREFERRED_NAME(iostream) _LIBCPP_PREFERRED_NAME(wiostream) basic_iostream; + +template + class _LIBCPP_PREFERRED_NAME(stringbuf) _LIBCPP_PREFERRED_NAME(wstringbuf) basic_stringbuf; +template + class _LIBCPP_PREFERRED_NAME(istringstream) _LIBCPP_PREFERRED_NAME(wistringstream) basic_istringstream; +template + class _LIBCPP_PREFERRED_NAME(ostringstream) _LIBCPP_PREFERRED_NAME(wostringstream) basic_ostringstream; +template + class _LIBCPP_PREFERRED_NAME(stringstream) _LIBCPP_PREFERRED_NAME(wstringstream) basic_stringstream; + +template + class _LIBCPP_PREFERRED_NAME(filebuf) _LIBCPP_PREFERRED_NAME(wfilebuf) basic_filebuf; +template + class _LIBCPP_PREFERRED_NAME(ifstream) _LIBCPP_PREFERRED_NAME(wifstream) basic_ifstream; +template + class _LIBCPP_PREFERRED_NAME(ofstream) _LIBCPP_PREFERRED_NAME(wofstream) basic_ofstream; +template + class _LIBCPP_PREFERRED_NAME(fstream) _LIBCPP_PREFERRED_NAME(wfstream) basic_fstream; + template class _LIBCPP_TEMPLATE_VIS fpos; typedef fpos streampos; typedef fpos wstreampos; @@ -210,6 +240,8 @@ template typedef basic_string, allocator > string; typedef basic_string, allocator > wstring; +template + class _LIBCPP_PREFERRED_NAME(string) _LIBCPP_PREFERRED_NAME(wstring) basic_string; // Include other forward declarations here template > diff --git a/libcxx/include/regex b/libcxx/include/regex index 7c5b2fd61b93..8578039bf6a2 100644 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -2534,7 +2534,17 @@ __exit: template class __lookahead; template > -class _LIBCPP_TEMPLATE_VIS basic_regex + class _LIBCPP_TEMPLATE_VIS basic_regex; + +typedef basic_regex regex; +typedef basic_regex wregex; + +template +class + _LIBCPP_TEMPLATE_VIS + _LIBCPP_PREFERRED_NAME(regex) + _LIBCPP_PREFERRED_NAME(wregex) + basic_regex { public: // types: @@ -4879,13 +4889,21 @@ basic_regex<_CharT, _Traits>::__push_lookahead(const basic_regex& __exp, __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } -typedef basic_regex regex; -typedef basic_regex wregex; - // sub_match +typedef sub_match csub_match; +typedef sub_match wcsub_match; +typedef sub_match ssub_match; +typedef sub_match wssub_match; + template -class _LIBCPP_TEMPLATE_VIS sub_match +class + _LIBCPP_TEMPLATE_VIS + _LIBCPP_PREFERRED_NAME(csub_match) + _LIBCPP_PREFERRED_NAME(wcsub_match) + _LIBCPP_PREFERRED_NAME(ssub_match) + _LIBCPP_PREFERRED_NAME(wssub_match) + sub_match : public pair<_BidirectionalIterator, _BidirectionalIterator> { public: @@ -4920,11 +4938,6 @@ public: {return str().compare(__s);} }; -typedef sub_match csub_match; -typedef sub_match wcsub_match; -typedef sub_match ssub_match; -typedef sub_match wssub_match; - template inline _LIBCPP_INLINE_VISIBILITY bool @@ -5307,8 +5320,19 @@ operator<<(basic_ostream<_CharT, _ST>& __os, const sub_match<_BiIter>& __m) return __os << __m.str(); } +typedef match_results cmatch; +typedef match_results wcmatch; +typedef match_results smatch; +typedef match_results wsmatch; + template -class _LIBCPP_TEMPLATE_VIS match_results +class + _LIBCPP_TEMPLATE_VIS + _LIBCPP_PREFERRED_NAME(cmatch) + _LIBCPP_PREFERRED_NAME(wcmatch) + _LIBCPP_PREFERRED_NAME(smatch) + _LIBCPP_PREFERRED_NAME(wsmatch) + match_results { public: typedef _Allocator allocator_type; @@ -5628,11 +5652,6 @@ match_results<_BidirectionalIterator, _Allocator>::swap(match_results& __m) swap(__ready_, __m.__ready_); } -typedef match_results cmatch; -typedef match_results wcmatch; -typedef match_results smatch; -typedef match_results wsmatch; - template bool operator==(const match_results<_BidirectionalIterator, _Allocator>& __x, @@ -6216,7 +6235,21 @@ regex_match(const basic_string<_CharT, _ST, _SA>& __s, template ::value_type, class _Traits = regex_traits<_CharT> > -class _LIBCPP_TEMPLATE_VIS regex_iterator + class _LIBCPP_TEMPLATE_VIS regex_iterator; + +typedef regex_iterator cregex_iterator; +typedef regex_iterator wcregex_iterator; +typedef regex_iterator sregex_iterator; +typedef regex_iterator wsregex_iterator; + +template +class + _LIBCPP_TEMPLATE_VIS + _LIBCPP_PREFERRED_NAME(cregex_iterator) + _LIBCPP_PREFERRED_NAME(wcregex_iterator) + _LIBCPP_PREFERRED_NAME(sregex_iterator) + _LIBCPP_PREFERRED_NAME(wsregex_iterator) + regex_iterator { public: typedef basic_regex<_CharT, _Traits> regex_type; @@ -6325,17 +6358,26 @@ regex_iterator<_BidirectionalIterator, _CharT, _Traits>::operator++() return *this; } -typedef regex_iterator cregex_iterator; -typedef regex_iterator wcregex_iterator; -typedef regex_iterator sregex_iterator; -typedef regex_iterator wsregex_iterator; - // regex_token_iterator template ::value_type, class _Traits = regex_traits<_CharT> > -class _LIBCPP_TEMPLATE_VIS regex_token_iterator + class _LIBCPP_TEMPLATE_VIS regex_token_iterator; + +typedef regex_token_iterator cregex_token_iterator; +typedef regex_token_iterator wcregex_token_iterator; +typedef regex_token_iterator sregex_token_iterator; +typedef regex_token_iterator wsregex_token_iterator; + +template +class + _LIBCPP_TEMPLATE_VIS + _LIBCPP_PREFERRED_NAME(cregex_token_iterator) + _LIBCPP_PREFERRED_NAME(wcregex_token_iterator) + _LIBCPP_PREFERRED_NAME(sregex_token_iterator) + _LIBCPP_PREFERRED_NAME(wsregex_token_iterator) + regex_token_iterator { public: typedef basic_regex<_CharT, _Traits> regex_type; @@ -6613,11 +6655,6 @@ regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>::operator++() return *this; } -typedef regex_token_iterator cregex_token_iterator; -typedef regex_token_iterator wcregex_token_iterator; -typedef regex_token_iterator sregex_token_iterator; -typedef regex_token_iterator wsregex_token_iterator; - // regex_replace template #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +#ifndef _LIBCPP_NO_HAS_CHAR8_T +typedef basic_string u8string; +#endif + +#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS +typedef basic_string u16string; +typedef basic_string u32string; +#endif // _LIBCPP_HAS_NO_UNICODE_CHARS + template -class _LIBCPP_TEMPLATE_VIS basic_string +class + _LIBCPP_TEMPLATE_VIS +#ifndef _LIBCPP_NO_HAS_CHAR8_T + _LIBCPP_PREFERRED_NAME(u8string) +#endif +#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS + _LIBCPP_PREFERRED_NAME(u16string) + _LIBCPP_PREFERRED_NAME(u32string) +#endif + basic_string : private __basic_string_common { public: @@ -4327,15 +4345,6 @@ swap(basic_string<_CharT, _Traits, _Allocator>& __lhs, __lhs.swap(__rhs); } -#ifndef _LIBCPP_NO_HAS_CHAR8_T -typedef basic_string u8string; -#endif - -#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS -typedef basic_string u16string; -typedef basic_string u32string; -#endif // _LIBCPP_HAS_NO_UNICODE_CHARS - _LIBCPP_FUNC_VIS int stoi (const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_FUNC_VIS long stol (const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_FUNC_VIS unsigned long stoul (const string& __str, size_t* __idx = nullptr, int __base = 10); diff --git a/libcxx/include/string_view b/libcxx/include/string_view index 7c3214fb2c2e..44ffb02c432d 100644 --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -192,7 +192,26 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template > -class _LIBCPP_TEMPLATE_VIS basic_string_view { + class _LIBCPP_TEMPLATE_VIS basic_string_view; + +typedef basic_string_view string_view; +#ifndef _LIBCPP_NO_HAS_CHAR8_T +typedef basic_string_view u8string_view; +#endif +typedef basic_string_view u16string_view; +typedef basic_string_view u32string_view; +typedef basic_string_view wstring_view; + +template +class + _LIBCPP_PREFERRED_NAME(string_view) +#ifndef _LIBCPP_NO_HAS_CHAR8_T + _LIBCPP_PREFERRED_NAME(u8string_view) +#endif + _LIBCPP_PREFERRED_NAME(u16string_view) + _LIBCPP_PREFERRED_NAME(u32string_view) + _LIBCPP_PREFERRED_NAME(wstring_view) + basic_string_view { public: // types typedef _Traits traits_type; @@ -776,14 +795,6 @@ basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, basic_string_view<_CharT, _Traits> __str); -typedef basic_string_view string_view; -#ifndef _LIBCPP_NO_HAS_CHAR8_T -typedef basic_string_view u8string_view; -#endif -typedef basic_string_view u16string_view; -typedef basic_string_view u32string_view; -typedef basic_string_view wstring_view; - // [string.view.hash] template struct _LIBCPP_TEMPLATE_VIS hash > >