diff options
author | David Majnemer <david.majnemer@gmail.com> | 2015-02-14 13:23:54 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2015-02-14 13:23:54 +0000 |
commit | 1dabfdcf6fb11bf6a1f13ce6e9b1294fc57b804f (patch) | |
tree | d9d14b2054959a0cc425d94d9c7938b374f3c54c | |
parent | 48d75034de6726f902494404114949a2ec82e5fb (diff) | |
download | bcm5719-llvm-1dabfdcf6fb11bf6a1f13ce6e9b1294fc57b804f.tar.gz bcm5719-llvm-1dabfdcf6fb11bf6a1f13ce6e9b1294fc57b804f.zip |
ItaniumMangle: Correctly mangle <base-unresolved-name>
We had two bugs:
- We were missing the "on" prefix for unresolved operators.
- We didn't handle the mangling of destructors at all.
This fixes PR22584.
llvm-svn: 229255
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 88 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle.cpp | 40 |
2 files changed, 95 insertions, 33 deletions
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index eae82a28273..fdb256434f6 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -372,6 +372,7 @@ private: void mangleAArch64NeonVectorType(const VectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); + void mangleMemberExprBase(const Expr *base, bool isArrow); void mangleMemberExpr(const Expr *base, bool isArrow, NestedNameSpecifier *qualifier, NamedDecl *firstQualifierLookup, @@ -1050,6 +1051,27 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, DeclarationName name, unsigned knownArity) { if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup); + switch (name.getNameKind()) { + // <base-unresolved-name> ::= <simple-id> + case DeclarationName::Identifier: + break; + // <base-unresolved-name> ::= on <operator-name> + case DeclarationName::CXXConversionFunctionName: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXOperatorName: + Out << "on"; + break; + case DeclarationName::CXXDestructorName: + llvm_unreachable("Can't mangle a constructor name!"); + case DeclarationName::CXXConstructorName: + llvm_unreachable("Can't mangle a constructor name!"); + case DeclarationName::CXXUsingDirective: + llvm_unreachable("Can't mangle a using directive name!"); + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCZeroArgSelector: + llvm_unreachable("Can't mangle Objective-C selector names here!"); + } mangleUnqualifiedName(nullptr, name, knownArity); } @@ -1532,7 +1554,8 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); assert(Dependent && "Unknown template name kind?"); - manglePrefix(Dependent->getQualifier()); + if (NestedNameSpecifier *Qualifier = Dependent->getQualifier()) + manglePrefix(Qualifier); mangleUnscopedTemplateName(Template); } @@ -2522,6 +2545,29 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T, } +void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) { + // Ignore member expressions involving anonymous unions. + while (const auto *RT = Base->getType()->getAs<RecordType>()) { + if (!RT->getDecl()->isAnonymousStructOrUnion()) + break; + const auto *ME = dyn_cast<MemberExpr>(Base); + if (!ME) + break; + Base = ME->getBase(); + IsArrow = ME->isArrow(); + } + + if (Base->isImplicitCXXThis()) { + // Note: GCC mangles member expressions to the implicit 'this' as + // *this., whereas we represent them as this->. The Itanium C++ ABI + // does not specify anything here, so we follow GCC. + Out << "dtdefpT"; + } else { + Out << (IsArrow ? "pt" : "dt"); + mangleExpression(Base); + } +} + /// Mangles a member expression. void CXXNameMangler::mangleMemberExpr(const Expr *base, bool isArrow, @@ -2531,29 +2577,8 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base, unsigned arity) { // <expression> ::= dt <expression> <unresolved-name> // ::= pt <expression> <unresolved-name> - if (base) { - - // Ignore member expressions involving anonymous unions. - while (const auto *RT = base->getType()->getAs<RecordType>()) { - if (!RT->getDecl()->isAnonymousStructOrUnion()) - break; - const auto *ME = dyn_cast<MemberExpr>(base); - if (!ME) - break; - base = ME->getBase(); - isArrow = ME->isArrow(); - } - - if (base->isImplicitCXXThis()) { - // Note: GCC mangles member expressions to the implicit 'this' as - // *this., whereas we represent them as this->. The Itanium C++ ABI - // does not specify anything here, so we follow GCC. - Out << "dtdefpT"; - } else { - Out << (isArrow ? "pt" : "dt"); - mangleExpression(base); - } - } + if (base) + mangleMemberExprBase(base, isArrow); mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity); } @@ -2651,7 +2676,6 @@ recurse: // FIXME: invent manglings for all these. case Expr::BlockExprClass: - case Expr::CXXPseudoDestructorExprClass: case Expr::ChooseExprClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: @@ -2809,6 +2833,20 @@ recurse: break; } + case Expr::CXXPseudoDestructorExprClass: { + const auto *PDE = cast<CXXPseudoDestructorExpr>(E); + if (const Expr *Base = PDE->getBase()) + mangleMemberExprBase(Base, PDE->isArrow()); + if (NestedNameSpecifier *Qualifier = PDE->getQualifier()) + mangleUnresolvedPrefix(Qualifier, /*FirstQualifierLookup=*/nullptr); + // <base-unresolved-name> ::= dn <destructor-name> + Out << "dn"; + // <destructor-name> ::= <unresolved-type> + // ::= <simple-id> + manglePrefix(PDE->getDestroyedType()); + break; + } + case Expr::MemberExprClass: { const MemberExpr *ME = cast<MemberExpr>(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp index 9af0d9da997..3b4123eace5 100644 --- a/clang/test/CodeGenCXX/mangle.cpp +++ b/clang/test/CodeGenCXX/mangle.cpp @@ -577,10 +577,10 @@ namespace test18 { template <typename T> void f(S<&T::operator&>) {} template void f<A>(S<&A::operator&>); - // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_plEEE - // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_miEEE - // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_mlEEE - // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_anEEE + // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_onplEEE + // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_onmiEEE + // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_onmlEEE + // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_onanEEE } // rdar://problem/8332117 @@ -601,11 +601,11 @@ namespace test19 { // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_1fIiEEEE( template void g<A>(S<&A::f<int> >); - // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_plEEE( + // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_onplEEE( template void g<A>(S<&A::operator+>); - // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_cviEEE( + // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_oncviEEE( template void g<A>(S<&A::operator int>); - // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_miIdEEEE( + // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_onmiIdEEEE( template void g<A>(S<&A::operator-<double> >); } @@ -839,7 +839,7 @@ namespace test35 { template<typename T> void f1(decltype(sizeof(&T::template operator+<int>))) {} - // CHECK-LABEL: define weak_odr void @_ZN6test352f1INS_1AEEEvDTszadsrT_plIiEE + // CHECK-LABEL: define weak_odr void @_ZN6test352f1INS_1AEEEvDTszadsrT_onplIiEE template void f1<A>(__SIZE_TYPE__); } @@ -1013,3 +1013,27 @@ namespace test50 { auto v = fin<S>; // CHECK-LABEL: declare void @_ZN6test503finINS_1SEEET_ILi3EES2_ILi4EE() } + +namespace test51 { + template <typename T> + decltype(T().~T()) fun() {} + template void fun<int>(); + // CHECK-LABEL: @_ZN6test513funIiEEDTcldtcvT__EdnS1_EEv + template void fun<X>(); + // CHECK-LABEL: @_ZN6test513funI1XEEDTcldtcvT__EdnS2_EEv + template void fun<S1<int> >(); + // CHECK-LABEL: @_ZN6test513funI2S1IiEEEDTcldtcvT__EdnS3_EEv + + template <typename T> + decltype(S1<T>().~S1<T>()) fun1() {}; + template <typename U, typename T> + decltype(U().~S1<T>()) fun2() {} + template <typename U, typename T> + decltype(S1<T>().~U()) fun3() {} + template void fun1<int>(); + // CHECK-LABEL: @_ZN6test514fun1IiEEDTcldtcv2S1IT_E_Edn2S1IS2_EEEv + template void fun2<S1<int>, int>(); + // CHECK-LABEL: @_ZN6test514fun2I2S1IiEiEEDTcldtcvT__Edn2S1IT0_EEEv + template void fun3<S1<int>, int>(); + // CHECK-LABEL: @_ZN6test514fun3I2S1IiEiEEDTcldtcvS1_IT0_E_EdnT_EEv +} |