diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 3bbc0a5767ff4..e7a5a6b6b8119 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4640,7 +4640,6 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, case Expr::ShuffleVectorExprClass: case Expr::ConvertVectorExprClass: case Expr::StmtExprClass: - case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::VAArgExprClass: @@ -4992,6 +4991,10 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, // If the result of the operator is implicitly converted to a known // integer type, that type is used for the literal; otherwise, the type // of std::size_t or std::ptrdiff_t is used. + // + // FIXME: We still include the operand in the profile in this case. This + // can lead to mangling collisions between function templates that we + // consider to be different. QualType T = (ImplicitlyConvertedToType.isNull() || !ImplicitlyConvertedToType->isIntegerType())? SAE->getType() : ImplicitlyConvertedToType; @@ -5054,6 +5057,20 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, break; } + case Expr::TypeTraitExprClass: { + // ::= u * E # vendor extension + const TypeTraitExpr *TTE = cast(E); + NotPrimaryExpr(); + Out << 'u'; + llvm::StringRef Spelling = getTraitSpelling(TTE->getTrait()); + Out << Spelling.size() << Spelling; + for (TypeSourceInfo *TSI : TTE->getArgs()) { + mangleType(TSI->getType()); + } + Out << 'E'; + break; + } + case Expr::CXXThrowExprClass: { NotPrimaryExpr(); const CXXThrowExpr *TE = cast(E); diff --git a/clang/test/CodeGenCXX/mangle-exprs.cpp b/clang/test/CodeGenCXX/mangle-exprs.cpp index 88406d7fe6d80..6ebca562caad5 100644 --- a/clang/test/CodeGenCXX/mangle-exprs.cpp +++ b/clang/test/CodeGenCXX/mangle-exprs.cpp @@ -389,3 +389,13 @@ namespace null { // CHECK-LABEL: define {{.*}} @_ZN4null8gnu_nullILPv0EEEvPN9enable_ifIXeqT_Ll0EEvE4typeE template void gnu_null(void *); } + +namespace type_trait { + template void f(decltype(__is_trivially_copyable(T))) {} + // CHECK-LABEL: define {{.*}} @_ZN10type_trait1fIiEEvDTu23__is_trivially_copyableT_EE + template void f(bool); + + template void g(decltype(__is_trivially_copyable(int) + T())) {} + // CHECK-LABEL: define {{.*}} @_ZN10type_trait1gIiEEvDTplu23__is_trivially_copyableiEcvT__EE + template void g(int); +}