aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2009-09-29 00:50:50 +0000
committerMike Stump <mrs@apple.com>2009-09-29 00:50:50 +0000
commit740256bafbba6c5b5cb95a5c5bd7db161f3b2833 (patch)
tree9f040e40577dcb0e432cf0c19afd316a528c0695
parentf8add9b5f51540e9e734e6a82c5d54c362be822a (diff)
Fix http://llvm.org/PR5090.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83035 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Decl.h1
-rw-r--r--include/clang/AST/DeclCXX.h7
-rw-r--r--include/clang/AST/Redeclarable.h9
-rw-r--r--lib/AST/Decl.cpp4
-rw-r--r--lib/CodeGen/CGCXX.cpp3
-rw-r--r--test/CodeGenCXX/virt.cpp13
6 files changed, 36 insertions, 1 deletions
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<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
+ }
+ CXXMethodDecl *getCanonicalDecl() {
+ return cast<CXXMethodDecl>(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<const decl_type*>(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<CXXDestructorDecl>(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;