From: Mike Stump Date: Tue, 29 Sep 2009 00:50:50 +0000 (+0000) Subject: Fix http://llvm.org/PR5090. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=740256bafbba6c5b5cb95a5c5bd7db161f3b2833;p=clang Fix http://llvm.org/PR5090. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83035 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 0b02ee26a8..4474719f36 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -973,6 +973,7 @@ public: void setPreviousDeclaration(FunctionDecl * PrevDecl); + virtual const FunctionDecl *getCanonicalDecl() const; virtual FunctionDecl *getCanonicalDecl(); unsigned getBuiltinID() const; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 4693034422..e4becf81cc 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -785,6 +785,13 @@ public: return (CD->begin_overridden_methods() != CD->end_overridden_methods()); } + const CXXMethodDecl *getCanonicalDecl() const { + return cast(FunctionDecl::getCanonicalDecl()); + } + CXXMethodDecl *getCanonicalDecl() { + return cast(FunctionDecl::getCanonicalDecl()); + } + /// void addOverriddenMethod(const CXXMethodDecl *MD); diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 5cd50686c5..458af1f144 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -79,6 +79,15 @@ public: return D; } + /// \brief Return the first declaration of this declaration or itself if this + /// is the only declaration. + const decl_type *getFirstDeclaration() const { + const decl_type *D = static_cast(this); + while (D->getPreviousDeclaration()) + D = D->getPreviousDeclaration(); + return D; + } + /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the /// first and only declaration. void setPreviousDeclaration(decl_type *PrevDecl) { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 25d3d44cc8..24dd3e5e3d 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -653,6 +653,10 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { } } +const FunctionDecl *FunctionDecl::getCanonicalDecl() const { + return getFirstDeclaration(); +} + FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDeclaration(); } diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 4c1f6ad4cd..e37b4a8548 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -221,7 +221,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { // virtual call mechanism. llvm::Value *Callee; if (MD->isVirtual() && !ME->hasQualifier()) - Callee = BuildVirtualCall(MD, This, Ty); + // FIXME: push getCanonicalDecl as a conversion using the static type system (CanCXXMethodDecl). + Callee = BuildVirtualCall(MD->getCanonicalDecl(), This, Ty); else if (const CXXDestructorDecl *Destructor = dyn_cast(MD)) Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty); diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index dfb705ae53..176009acc4 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -920,6 +920,19 @@ struct test13_D : test13_NV1, virtual test13_B2 { // CHECK-LP64-NEXT: .quad __ZN2D14bar4Ev // CHECK-LP64-NEXT: .quad __ZN2D14bar5Ev +class test14 { +public: + virtual void initWithInt(int a); + static test14 *withInt(int a); +}; + +void test14::initWithInt(int a) { } + +test14 *test14::withInt(int a) { + test14 *me = new test14; + me->initWithInt(a); + return me; +} test11_D d11; test10_D d10;