From: John McCall Date: Thu, 28 Apr 2011 02:52:03 +0000 (+0000) Subject: Implement the mangling for non-ADL call expressions that we just X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5a7e6f781afc53f3c04c146d74aa7eff15f1338e;p=clang Implement the mangling for non-ADL call expressions that we just worked out. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130376 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 82de578412..04d705eb1a 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1849,11 +1849,41 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base, mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity); } +/// Look at the callee of the given call expression and determine if +/// it's a parenthesized id-expression which would have triggered ADL +/// otherwise. +static bool isParenthesizedADLCallee(const CallExpr *call) { + const Expr *callee = call->getCallee(); + const Expr *fn = callee->IgnoreParens(); + + // Must be parenthesized. IgnoreParens() skips __extension__ nodes, + // too, but for those to appear in the callee, it would have to be + // parenthesized. + if (callee == fn) return false; + + // Must be an unresolved lookup. + const UnresolvedLookupExpr *lookup = dyn_cast(fn); + if (!lookup) return false; + + assert(!lookup->requiresADL()); + + // Must be an unqualified lookup. + if (lookup->getQualifier()) return false; + + // Must not have found a class member. Note that if one is a class + // member, they're all class members. + if (lookup->getNumDecls() > 0 && + (*lookup->decls_begin())->isCXXClassMember()) + return false; + + // Otherwise, ADL would have been triggered. + return true; +} + void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { // ::= // ::= // ::= - // ::= cl * E # call // ::= cv expression # conversion with one argument // ::= cv _ * E # conversion with a different number of arguments // ::= st # sizeof (a type) @@ -1948,7 +1978,22 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::CXXMemberCallExprClass: // fallthrough case Expr::CallExprClass: { const CallExpr *CE = cast(E); - Out << "cl"; + + // ::= cp * E + // We use this mangling only when the call would use ADL except + // for being parenthesized. Per discussion with David + // Vandervoorde, 2011.04.25. + if (isParenthesizedADLCallee(CE)) { + Out << "cp"; + // The callee here is a parenthesized UnresolvedLookupExpr with + // no qualifier and should always get mangled as a + // anyway. + + // ::= cl * E + } else { + Out << "cl"; + } + mangleExpression(CE->getCallee(), CE->getNumArgs()); for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I) mangleExpression(CE->getArg(I)); diff --git a/test/CodeGenCXX/mangle-exprs.cpp b/test/CodeGenCXX/mangle-exprs.cpp index e5f26e584b..5014a9145e 100644 --- a/test/CodeGenCXX/mangle-exprs.cpp +++ b/test/CodeGenCXX/mangle-exprs.cpp @@ -49,3 +49,19 @@ namespace Casts { // CHECK: define weak_odr void @_ZN5Casts5auto_IiEEvDTnw_DapicvT__EEE( template void auto_(int*); } + +namespace test1 { + short foo(short); + int foo(int); + + // CHECK: define linkonce_odr signext i16 @_ZN5test11aIsEEDTcl3foocvT__EEES1_( + template auto a(T t) -> decltype(foo(T())) { return foo(t); } + + // CHECK: define linkonce_odr signext i16 @_ZN5test11bIsEEDTcp3foocvT__EEES1_( + template auto b(T t) -> decltype((foo)(T())) { return (foo)(t); } + + void test(short s) { + a(s); + b(s); + } +}