summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-05-25 00:33:13 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-05-25 00:33:13 +0000
commit532177685a64a84fc9f45c729f328ec3ddcfa7cc (patch)
treed2ca420c36c2ae4e3c4465992f01fbb32b3be608
parent105ce6db873f80fb8737e5eda365df4c8e2855fd (diff)
downloadbcm5719-llvm-532177685a64a84fc9f45c729f328ec3ddcfa7cc.tar.gz
bcm5719-llvm-532177685a64a84fc9f45c729f328ec3ddcfa7cc.zip
IRgen/C++: When mark vtables used, make sure to still append to the VTableUse array if we promote a vtable from being just used to having its definition required. This ensures that we properly inform the consumer about whether the vtable is required or not, previously we could fail to do so when the vtable was in the VTableUses array before the decl which marked it as required.
- I think this can be cleaned up, since this means we may notify the consumer about the vtable twice, but I didn't see an easy fix for this without more substantial refactoring. - Doug, please review! llvm-svn: 104577
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp11
-rw-r--r--clang/test/CodeGenCXX/vtable-linkage.cpp16
2 files changed, 24 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index d2655cb6256..60f3fe92832 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6085,8 +6085,15 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool>
Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
if (!Pos.second) {
- Pos.first->second = Pos.first->second || DefinitionRequired;
- return;
+ // If we already had an entry, check to see if we are promoting this vtable
+ // to required a definition. If so, we need to reappend to the VTableUses
+ // list, since we may have already processed the first entry.
+ if (DefinitionRequired && !Pos.first->second) {
+ Pos.first->second = true;
+ } else {
+ // Otherwise, we can early exit.
+ return;
+ }
}
// Local classes need to have their virtual members marked
diff --git a/clang/test/CodeGenCXX/vtable-linkage.cpp b/clang/test/CodeGenCXX/vtable-linkage.cpp
index 02b1d5c7483..b3b68703c6d 100644
--- a/clang/test/CodeGenCXX/vtable-linkage.cpp
+++ b/clang/test/CodeGenCXX/vtable-linkage.cpp
@@ -160,4 +160,18 @@ void use_F(F<char> &fc) {
// CHECK-12: @_ZTSN12_GLOBAL__N_11AE = internal constant
// CHECK-12: @_ZTIN12_GLOBAL__N_11AE = internal constant
-
+// RUN: FileCheck --check-prefix=CHECK-G %s < %t
+//
+// CHECK-G: @_ZTV1GIiE = weak_odr constant
+template <typename T>
+class G {
+public:
+ G() {}
+ virtual void f0();
+ virtual void f1();
+};
+template <>
+void G<int>::f1() {}
+template <typename T>
+void G<T>::f0() {}
+void G_f0() { new G<int>(); }
OpenPOWER on IntegriCloud