Skip to content

Commit 53eaee6

Browse files
urnathantstellar
authored andcommitted
[clang][NFC] Standard substitution checking cleanup
In preparing for module mangling changes I noticed some issues with the way we check for std::basic_string instantiations and friends. *) there's a single routine for std::basic_{i,o,io}stream but it is templatized on the length of the name. Really? just use a StringRef, rather than clone the entire routine just for 'basic_iostream'. *) We have a helper routine to check for char type, and call it from several places. But given all the instantiations are of the form TPL<char, Other<char> ...> we could just check the first arg is char and the later templated args are instantiating that same type. A simpler type comparison. *) Because basic_string has a third allocator parameter, it is open coded, which I found a little confusing. But otherwise it's exactly the same pattern as the iostream ones. Just tell that checker about whether there's an expected allocator argument.[*] *) We may as well return in each block of mangleStandardSubstitution once we determine it is not one of the entities of interest -- it certainly cannot be one of the other kinds of entities. FWIW this shaves about 500 bytes off the executable. [*] I suppose we could also have this routine a tri-value, with one to indicat 'it is this name, but it's not the one you're looking for', to avoid later calls trying different names? Reviewd By: ChuanqiXu Differential Revision: https://reviews.llvm.org/D119333
1 parent c81f3d0 commit 53eaee6

File tree

1 file changed

+34
-41
lines changed

1 file changed

+34
-41
lines changed

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5969,27 +5969,19 @@ bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
59695969
return true;
59705970
}
59715971

5972-
static bool isCharType(QualType T) {
5973-
if (T.isNull())
5972+
/// Returns whether S is a template specialization of std::Name with a single
5973+
/// argument of type A.
5974+
static bool isSpecializedAs(QualType S, llvm::StringRef Name, QualType A) {
5975+
if (S.isNull())
59745976
return false;
59755977

5976-
return T->isSpecificBuiltinType(BuiltinType::Char_S) ||
5977-
T->isSpecificBuiltinType(BuiltinType::Char_U);
5978-
}
5979-
5980-
/// Returns whether a given type is a template specialization of a given name
5981-
/// with a single argument of type char.
5982-
static bool isCharSpecialization(QualType T, const char *Name) {
5983-
if (T.isNull())
5984-
return false;
5985-
5986-
const RecordType *RT = T->getAs<RecordType>();
5978+
const RecordType *RT = S->getAs<RecordType>();
59875979
if (!RT)
59885980
return false;
59895981

59905982
const ClassTemplateSpecializationDecl *SD =
59915983
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
5992-
if (!SD)
5984+
if (!SD || !SD->getIdentifier()->isStr(Name))
59935985
return false;
59945986

59955987
if (!isStdNamespace(getEffectiveDeclContext(SD)))
@@ -5999,26 +5991,37 @@ static bool isCharSpecialization(QualType T, const char *Name) {
59995991
if (TemplateArgs.size() != 1)
60005992
return false;
60015993

6002-
if (!isCharType(TemplateArgs[0].getAsType()))
5994+
if (TemplateArgs[0].getAsType() != A)
60035995
return false;
60045996

6005-
return SD->getIdentifier()->getName() == Name;
5997+
return true;
60065998
}
60075999

6008-
template <std::size_t StrLen>
6009-
static bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl*SD,
6010-
const char (&Str)[StrLen]) {
6011-
if (!SD->getIdentifier()->isStr(Str))
6000+
/// Returns whether SD is a template specialization std::Name<char,
6001+
/// std::char_traits<char> [, std::allocator<char>]>
6002+
/// HasAllocator controls whether the 3rd template argument is needed.
6003+
static bool isStdCharSpecialization(const ClassTemplateSpecializationDecl *SD,
6004+
llvm::StringRef Name, bool HasAllocator) {
6005+
if (!SD->getIdentifier()->isStr(Name))
60126006
return false;
60136007

60146008
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
6015-
if (TemplateArgs.size() != 2)
6009+
if (TemplateArgs.size() != (HasAllocator ? 3 : 2))
60166010
return false;
60176011

6018-
if (!isCharType(TemplateArgs[0].getAsType()))
6012+
QualType A = TemplateArgs[0].getAsType();
6013+
if (A.isNull())
6014+
return false;
6015+
// Plain 'char' is named Char_S or Char_U depending on the target ABI.
6016+
if (!A->isSpecificBuiltinType(BuiltinType::Char_S) &&
6017+
!A->isSpecificBuiltinType(BuiltinType::Char_U))
60196018
return false;
60206019

6021-
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
6020+
if (!isSpecializedAs(TemplateArgs[1].getAsType(), "char_traits", A))
6021+
return false;
6022+
6023+
if (HasAllocator &&
6024+
!isSpecializedAs(TemplateArgs[2].getAsType(), "allocator", A))
60226025
return false;
60236026

60246027
return true;
@@ -6031,6 +6034,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
60316034
Out << "St";
60326035
return true;
60336036
}
6037+
return false;
60346038
}
60356039

60366040
if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
@@ -6048,6 +6052,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
60486052
Out << "Sb";
60496053
return true;
60506054
}
6055+
return false;
60516056
}
60526057

60536058
if (const ClassTemplateSpecializationDecl *SD =
@@ -6058,46 +6063,34 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
60586063
// <substitution> ::= Ss # ::std::basic_string<char,
60596064
// ::std::char_traits<char>,
60606065
// ::std::allocator<char> >
6061-
if (SD->getIdentifier()->isStr("basic_string")) {
6062-
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
6063-
6064-
if (TemplateArgs.size() != 3)
6065-
return false;
6066-
6067-
if (!isCharType(TemplateArgs[0].getAsType()))
6068-
return false;
6069-
6070-
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
6071-
return false;
6072-
6073-
if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator"))
6074-
return false;
6075-
6066+
if (isStdCharSpecialization(SD, "basic_string", /*HasAllocator=*/true)) {
60766067
Out << "Ss";
60776068
return true;
60786069
}
60796070

60806071
// <substitution> ::= Si # ::std::basic_istream<char,
60816072
// ::std::char_traits<char> >
6082-
if (isStreamCharSpecialization(SD, "basic_istream")) {
6073+
if (isStdCharSpecialization(SD, "basic_istream", /*HasAllocator=*/false)) {
60836074
Out << "Si";
60846075
return true;
60856076
}
60866077

60876078
// <substitution> ::= So # ::std::basic_ostream<char,
60886079
// ::std::char_traits<char> >
6089-
if (isStreamCharSpecialization(SD, "basic_ostream")) {
6080+
if (isStdCharSpecialization(SD, "basic_ostream", /*HasAllocator=*/false)) {
60906081
Out << "So";
60916082
return true;
60926083
}
60936084

60946085
// <substitution> ::= Sd # ::std::basic_iostream<char,
60956086
// ::std::char_traits<char> >
6096-
if (isStreamCharSpecialization(SD, "basic_iostream")) {
6087+
if (isStdCharSpecialization(SD, "basic_iostream", /*HasAllocator=*/false)) {
60976088
Out << "Sd";
60986089
return true;
60996090
}
6091+
return false;
61006092
}
6093+
61016094
return false;
61026095
}
61036096

0 commit comments

Comments
 (0)