diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-03-05 23:38:39 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-03-05 23:38:39 +0000 |
| commit | 6de584c2d2fc3a5c24a2fd789c0ca83d555c104e (patch) | |
| tree | 7e6ed14c147f49db14def26fca70ce26c75e3efa /clang/lib | |
| parent | 0a3d71af5218232b1006105bc3ceb08f52da1117 (diff) | |
| download | bcm5719-llvm-6de584c2d2fc3a5c24a2fd789c0ca83d555c104e.tar.gz bcm5719-llvm-6de584c2d2fc3a5c24a2fd789c0ca83d555c104e.zip | |
When declaring a catch block in C++, make sure that the type being
caught can be copy-initialized and destructed. Fixes PR6518.
llvm-svn: 97853
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 574b2250278..0708d4176a4 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5212,14 +5212,35 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, AbstractVariableType)) Invalid = true; - // FIXME: Need to test for ability to copy-construct and destroy the - // exception variable. - - // FIXME: Need to check for abstract classes. - VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc, Name, ExDeclType, TInfo, VarDecl::None); + if (!Invalid) { + if (const RecordType *RecordTy = ExDeclType->getAs<RecordType>()) { + // C++ [except.handle]p16: + // The object declared in an exception-declaration or, if the + // exception-declaration does not specify a name, a temporary (12.2) is + // copy-initialized (8.5) from the exception object. [...] + // The object is destroyed when the handler exits, after the destruction + // of any automatic objects initialized within the handler. + // + // We just pretend to initialize the object with itself, then make sure + // it can be destroyed later. + InitializedEntity Entity = InitializedEntity::InitializeVariable(ExDecl); + Expr *ExDeclRef = DeclRefExpr::Create(Context, 0, SourceRange(), ExDecl, + Loc, ExDeclType, 0); + InitializationKind Kind = InitializationKind::CreateCopy(Loc, + SourceLocation()); + InitializationSequence InitSeq(*this, Entity, Kind, &ExDeclRef, 1); + OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&ExDeclRef, 1)); + if (Result.isInvalid()) + Invalid = true; + else + FinalizeVarWithDestructor(ExDecl, RecordTy); + } + } + if (Invalid) ExDecl->setInvalidDecl(); |

