diff options
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 9 | ||||
| -rw-r--r-- | clang/test/CXX/special/class.dtor/p9.cpp | 7 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/key-function-vtable.cpp | 2 | ||||
| -rw-r--r-- | clang/test/SemaCXX/devirtualize-vtable-marking.cpp | 15 | ||||
| -rw-r--r-- | clang/test/SemaCXX/microsoft-dtor-lookup.cpp | 3 | ||||
| -rw-r--r-- | clang/test/SemaCXX/warn-weak-vtables.cpp | 26 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/virtual-member-functions.cpp | 4 |
12 files changed, 35 insertions, 69 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a53eda41e1f..f6d185e4916 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5182,8 +5182,6 @@ public: // FIXME: I don't like this name. void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath); - bool BasePathInvolvesVirtualBase(const CXXCastPath &BasePath); - bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, CXXCastPath *BasePath = nullptr, diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index b9aaf1616d6..ded6c303af8 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -337,18 +337,6 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, if (ExprTy == TypeTy) return E; - // If this is a derived-to-base cast to a through a virtual base, we - // need a vtable. - if (Kind == CK_DerivedToBase && - BasePathInvolvesVirtualBase(*BasePath)) { - QualType T = E->getType(); - if (const PointerType *Pointer = T->getAs<PointerType>()) - T = Pointer->getPointeeType(); - if (const RecordType *RecordTy = T->getAs<RecordType>()) - MarkVTableUsed(E->getLocStart(), - cast<CXXRecordDecl>(RecordTy->getDecl())); - } - if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) { if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { ImpCast->setType(Ty); diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index a4c2d9b51c2..3e06a6477d6 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -665,12 +665,6 @@ void CastOperation::CheckDynamicCast() { } Kind = CK_DerivedToBase; - - // If we are casting to or through a virtual base class, we need a - // vtable. - if (Self.BasePathInvolvesVirtualBase(BasePath)) - Self.MarkVTableUsed(OpRange.getBegin(), - cast<CXXRecordDecl>(SrcRecord->getDecl())); return; } @@ -682,8 +676,6 @@ void CastOperation::CheckDynamicCast() { << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); SrcExpr = ExprError(); } - Self.MarkVTableUsed(OpRange.getBegin(), - cast<CXXRecordDecl>(SrcRecord->getDecl())); // dynamic_cast is not available with -fno-rtti. // As an exception, dynamic_cast to void* is available because it doesn't diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 1b9ccee9dbe..79732c354ca 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1745,18 +1745,6 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths, BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base)); } -/// \brief Determine whether the given base path includes a virtual -/// base class. -bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) { - for (CXXCastPath::const_iterator B = BasePath.begin(), - BEnd = BasePath.end(); - B != BEnd; ++B) - if ((*B)->isVirtual()) - return true; - - return false; -} - /// CheckDerivedToBaseConversion - Check whether the Derived-to-Base /// conversion (where Derived and Base are class types) is /// well-formed, meaning that the conversion is unambiguous (and diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4114b567136..8b9950847f5 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11621,7 +11621,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, Destructor = cast<CXXDestructorDecl>(Destructor->getFirstDecl()); if (Destructor->isDefaulted() && !Destructor->isDeleted()) DefineImplicitDestructor(Loc, Destructor); - if (Destructor->isVirtual()) + if (Destructor->isVirtual() && getLangOpts().AppleKext) MarkVTableUsed(Loc, Destructor->getParent()); } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(Func)) { if (MethodDecl->isOverloadedOperator() && @@ -11641,7 +11641,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, DefineImplicitLambdaToBlockPointerConversion(Loc, Conversion); else DefineImplicitLambdaToFunctionPointerConversion(Loc, Conversion); - } else if (MethodDecl->isVirtual()) + } else if (MethodDecl->isVirtual() && getLangOpts().AppleKext) MarkVTableUsed(Loc, MethodDecl->getParent()); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index e7a8e9cacde..9aca373d97b 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -5880,15 +5880,6 @@ InitializationSequence::Perform(Sema &S, &BasePath, IgnoreBaseAccess)) return ExprError(); - if (S.BasePathInvolvesVirtualBase(BasePath)) { - QualType T = SourceType; - if (const PointerType *Pointer = T->getAs<PointerType>()) - T = Pointer->getPointeeType(); - if (const RecordType *RecordTy = T->getAs<RecordType>()) - S.MarkVTableUsed(CurInit.get()->getLocStart(), - cast<CXXRecordDecl>(RecordTy->getDecl())); - } - ExprValueKind VK = Step->Kind == SK_CastDerivedToBaseLValue ? VK_LValue : diff --git a/clang/test/CXX/special/class.dtor/p9.cpp b/clang/test/CXX/special/class.dtor/p9.cpp index a03fcdb2495..42a4236a4a0 100644 --- a/clang/test/CXX/special/class.dtor/p9.cpp +++ b/clang/test/CXX/special/class.dtor/p9.cpp @@ -89,4 +89,11 @@ namespace test3 { virtual ~B() {} static void operator delete(void*); }; + + void f() { +#ifdef MSABI + // expected-note@+2 {{implicit default constructor for 'test3::B' first required here}} +#endif + B use_vtable; + } } diff --git a/clang/test/CodeGenCXX/key-function-vtable.cpp b/clang/test/CodeGenCXX/key-function-vtable.cpp index c443b5277e4..80ce497505d 100644 --- a/clang/test/CodeGenCXX/key-function-vtable.cpp +++ b/clang/test/CodeGenCXX/key-function-vtable.cpp @@ -41,7 +41,7 @@ struct X1 : X0 { inline void X1::f() { } -void use_X1(X1 *x1) { x1->f(); } +void use_X1() { X1 x1; } // FIXME: The checks are extremely difficult to get right when the globals // aren't alphabetized diff --git a/clang/test/SemaCXX/devirtualize-vtable-marking.cpp b/clang/test/SemaCXX/devirtualize-vtable-marking.cpp index fc3e8ce7704..1b32182c4f2 100644 --- a/clang/test/SemaCXX/devirtualize-vtable-marking.cpp +++ b/clang/test/SemaCXX/devirtualize-vtable-marking.cpp @@ -1,29 +1,32 @@ // RUN: %clang_cc1 -verify -std=c++11 %s - +// expected-no-diagnostics template <typename T> struct OwnPtr { T *p; ~OwnPtr() { - // expected-error@+1 {{invalid application of 'sizeof'}} static_assert(sizeof(T) > 0, "incomplete T"); delete p; } }; namespace use_vtable_for_vcall { -struct Incomplete; // expected-note {{forward declaration}} +struct Incomplete; struct A { virtual ~A() {} virtual void m() {} }; -struct B : A { // expected-note {{in instantiation}} +struct B : A { B(); virtual void m() { } virtual void m2() { static_cast<A *>(this)->m(); } OwnPtr<Incomplete> m_sqlError; }; -B *f() { - return new B(); +void f() { + // Since B's constructor is declared out of line, nothing in this file + // references a vtable, so the destructor doesn't get built. + A *b = new B(); + b->m(); + delete b; } } diff --git a/clang/test/SemaCXX/microsoft-dtor-lookup.cpp b/clang/test/SemaCXX/microsoft-dtor-lookup.cpp index 412749f707e..312598e2863 100644 --- a/clang/test/SemaCXX/microsoft-dtor-lookup.cpp +++ b/clang/test/SemaCXX/microsoft-dtor-lookup.cpp @@ -23,8 +23,9 @@ struct VC : A, B { virtual ~VC(); // expected-error {{member 'operator delete' found in multiple base classes of different types}} }; -void f(VC vc) { +void f() { // This marks VC's vtable used. + VC vc; } } diff --git a/clang/test/SemaCXX/warn-weak-vtables.cpp b/clang/test/SemaCXX/warn-weak-vtables.cpp index 671ff297cfa..d3066538715 100644 --- a/clang/test/SemaCXX/warn-weak-vtables.cpp +++ b/clang/test/SemaCXX/warn-weak-vtables.cpp @@ -20,15 +20,14 @@ void f() { virtual void f() { } }; - A *a; - a->f(); + A a; } // Use the vtables -void uses(A &a, B<int> &b, C &c) { - a.f(); - b.f(); - c.f(); +void uses_abc() { + A a; + B<int> b; + C c; } // <rdar://problem/9979458> @@ -52,10 +51,9 @@ public: Parent::~Parent() {} -void uses(Parent &p, Derived &d, VeryDerived &vd) { - p.getFoo(); - d.getFoo(); - vd.getFoo(); +void uses_derived() { + Derived d; + VeryDerived vd; } template<typename T> struct TemplVirt { @@ -72,8 +70,8 @@ template<> struct TemplVirt<long> { // expected-warning{{'TemplVirt<long>' has n virtual void f() {} }; -void uses(TemplVirt<float>& f, TemplVirt<bool>& b, TemplVirt<long>& l) { - f.f(); - b.f(); - l.f(); +void uses_templ() { + TemplVirt<float> f; + TemplVirt<bool> b; + TemplVirt<long> l; } diff --git a/clang/test/SemaTemplate/virtual-member-functions.cpp b/clang/test/SemaTemplate/virtual-member-functions.cpp index c2fc2634edd..4044f9e513d 100644 --- a/clang/test/SemaTemplate/virtual-member-functions.cpp +++ b/clang/test/SemaTemplate/virtual-member-functions.cpp @@ -110,12 +110,12 @@ namespace PR7114 { namespace DynamicCast { struct Y {}; template<typename T> struct X : virtual Y { - virtual void foo() { T x; } // expected-error {{variable has incomplete type 'void'}} + virtual void foo() { T x; } }; template<typename T> struct X2 : virtual Y { virtual void foo() { T x; } }; - Y* f(X<void>* x) { return dynamic_cast<Y*>(x); } // expected-note {{in instantiation of member function 'DynamicCast::X<void>::foo' requested here}} + Y* f(X<void>* x) { return dynamic_cast<Y*>(x); } Y* f2(X<void>* x) { return dynamic_cast<Y*>(x); } } |

