diff options
author | John McCall <rjmccall@apple.com> | 2010-09-17 02:31:44 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-09-17 02:31:44 +0000 |
commit | 769250ea70ca5af63c014453332bfa1d77ed556b (patch) | |
tree | c516d76aa1e7ebf19643ad0dad3188c0aee836a5 /clang/lib/CodeGen/CGClass.cpp | |
parent | 6fe64b528d6b8e666da2f2bda62ff1565a9be601 (diff) | |
download | bcm5719-llvm-769250ea70ca5af63c014453332bfa1d77ed556b.tar.gz bcm5719-llvm-769250ea70ca5af63c014453332bfa1d77ed556b.zip |
Currently we're initializing the vtable pointers of a class only after
the bases are completely initialized. This won't work --- base
initializer expressions can rely on the vtables having been set up.
Check for uses of 'this' in the initializers and force a vtable
initialization if found.
This might not be good enough; we might need to extend this to handle
the possibility of arbitrary code finding an external reference to this
(not yet completely-constructed!) object and accessing through it,
in which case we'll probably find ourselves doing a lot more unnecessary
stores.
llvm-svn: 114153
Diffstat (limited to 'clang/lib/CodeGen/CGClass.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index a6ac0acfb9a..c8f23f3f0c6 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -14,6 +14,7 @@ #include "CGDebugInfo.h" #include "CodeGenFunction.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtCXX.h" @@ -334,6 +335,29 @@ namespace { CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, Addr); } }; + + /// A visitor which checks whether an initializer uses 'this' in a + /// way which requires the vtable to be properly set. + struct DynamicThisUseChecker : EvaluatedExprVisitor<DynamicThisUseChecker> { + typedef EvaluatedExprVisitor<DynamicThisUseChecker> super; + + bool UsesThis; + + DynamicThisUseChecker(ASTContext &C) : super(C), UsesThis(false) {} + + // Black-list all explicit and implicit references to 'this'. + // + // Do we need to worry about external references to 'this' derived + // from arbitrary code? If so, then anything which runs arbitrary + // external code might potentially access the vtable. + void VisitCXXThisExpr(CXXThisExpr *E) { UsesThis = true; } + }; +} + +static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) { + DynamicThisUseChecker Checker(C); + Checker.Visit(const_cast<Expr*>(Init)); + return Checker.UsesThis; } static void EmitBaseInitializer(CodeGenFunction &CGF, @@ -355,6 +379,12 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, if (CtorType == Ctor_Base && isBaseVirtual) return; + // If the initializer for the base (other than the constructor + // itself) accesses 'this' in any way, we need to initialize the + // vtables. + if (BaseInitializerUsesThis(CGF.getContext(), BaseInit->getInit())) + CGF.InitializeVTablePointers(ClassDecl); + // We can pretend to be a complete class because it only matters for // virtual bases, and we only do virtual bases for complete ctors. llvm::Value *V = |