diff options
author | John Wiegley <johnw@boostpro.com> | 2011-04-28 01:08:34 +0000 |
---|---|---|
committer | John Wiegley <johnw@boostpro.com> | 2011-04-28 01:08:34 +0000 |
commit | 28bbe4b8acc338476fe0825769b41fb32b423c72 (patch) | |
tree | 93a24e53fba644d6caa1db0b82cd678ef8fb0f8d /lib | |
parent | 61d0b6baf47cf411f6c0f6ddb4acffcfeec724f1 (diff) |
Parsing/AST support for Structured Exception Handling
Patch authored by Sohail Somani.
Provide parsing and AST support for Windows structured exception handling.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130366 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Stmt.cpp | 58 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 42 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 4 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 51 | ||||
-rw-r--r-- | lib/Lex/TokenLexer.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 159 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 28 | ||||
-rw-r--r-- | lib/Parse/RAIIObjectsForParser.h | 26 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 72 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 3 |
13 files changed, 471 insertions, 25 deletions
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 5b0db8621a..380ad94ca2 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -710,3 +710,61 @@ const Expr* ReturnStmt::getRetValue() const { Expr* ReturnStmt::getRetValue() { return cast_or_null<Expr>(RetExpr); } + +SEHTryStmt::SEHTryStmt(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) + : Stmt(SEHTryStmtClass), + IsCXXTry(IsCXXTry), + TryLoc(TryLoc) +{ + Children[TRY] = TryBlock; + Children[HANDLER] = Handler; +} + +SEHTryStmt* SEHTryStmt::Create(ASTContext &C, + bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { + return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler); +} + +SEHExceptStmt* SEHTryStmt::getExceptHandler() const { + return dyn_cast<SEHExceptStmt>(getHandler()); +} + +SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const { + return dyn_cast<SEHFinallyStmt>(getHandler()); +} + +SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) + : Stmt(SEHExceptStmtClass), + Loc(Loc) +{ + Children[FILTER_EXPR] = reinterpret_cast<Stmt*>(FilterExpr); + Children[BLOCK] = Block; +} + +SEHExceptStmt* SEHExceptStmt::Create(ASTContext &C, + SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) { + return new(C) SEHExceptStmt(Loc,FilterExpr,Block); +} + +SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, + Stmt *Block) + : Stmt(SEHFinallyStmtClass), + Loc(Loc), + Block(Block) +{} + +SEHFinallyStmt* SEHFinallyStmt::Create(ASTContext &C, + SourceLocation Loc, + Stmt *Block) { + return new(C)SEHFinallyStmt(Loc,Block); +} diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 62f06dba16..fa0e091d29 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -66,6 +66,8 @@ namespace { void PrintRawIfStmt(IfStmt *If); void PrintRawCXXCatchStmt(CXXCatchStmt *Catch); void PrintCallArgs(CallExpr *E); + void PrintRawSEHExceptHandler(SEHExceptStmt *S); + void PrintRawSEHFinallyStmt(SEHFinallyStmt *S); void PrintExpr(Expr *E) { if (E) @@ -473,6 +475,46 @@ void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) { OS << "\n"; } +void StmtPrinter::VisitSEHTryStmt(SEHTryStmt *Node) { + Indent() << (Node->getIsCXXTry() ? "try " : "__try "); + PrintRawCompoundStmt(Node->getTryBlock()); + SEHExceptStmt *E = Node->getExceptHandler(); + SEHFinallyStmt *F = Node->getFinallyHandler(); + if(E) + PrintRawSEHExceptHandler(E); + else { + assert(F && "Must have a finally block..."); + PrintRawSEHFinallyStmt(F); + } + OS << "\n"; +} + +void StmtPrinter::PrintRawSEHFinallyStmt(SEHFinallyStmt *Node) { + OS << "__finally "; + PrintRawCompoundStmt(Node->getBlock()); + OS << "\n"; +} + +void StmtPrinter::PrintRawSEHExceptHandler(SEHExceptStmt *Node) { + OS << "__except ("; + VisitExpr(Node->getFilterExpr()); + OS << ")\n"; + PrintRawCompoundStmt(Node->getBlock()); + OS << "\n"; +} + +void StmtPrinter::VisitSEHExceptStmt(SEHExceptStmt *Node) { + Indent(); + PrintRawSEHExceptHandler(Node); + OS << "\n"; +} + +void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) { + Indent(); + PrintRawSEHFinallyStmt(Node); + OS << "\n"; +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 7a3fc5417c..17383c137a 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -181,6 +181,18 @@ void StmtProfiler::VisitCXXForRangeStmt(CXXForRangeStmt *S) { VisitStmt(S); } +void StmtProfiler::VisitSEHTryStmt(SEHTryStmt *S) { + VisitStmt(S); +} + +void StmtProfiler::VisitSEHFinallyStmt(SEHFinallyStmt *S) { + VisitStmt(S); +} + +void StmtProfiler::VisitSEHExceptStmt(SEHExceptStmt *S) { + VisitStmt(S); +} + void StmtProfiler::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { VisitStmt(S); } diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 0acedeffaf..99bc3f49ce 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -72,6 +72,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { switch (S->getStmtClass()) { case Stmt::NoStmtClass: case Stmt::CXXCatchStmtClass: + case Stmt::SEHExceptStmtClass: + case Stmt::SEHFinallyStmtClass: llvm_unreachable("invalid statement class to emit generically"); case Stmt::NullStmtClass: case Stmt::CompoundStmtClass: @@ -155,6 +157,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { break; case Stmt::CXXForRangeStmtClass: EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*S)); + case Stmt::SEHTryStmtClass: + // FIXME Not yet implemented break; } } diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index f5cdb015e9..31fd667a65 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -89,6 +89,7 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts, // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro. // This gets unpoisoned where it is allowed. (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned(); + SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use); // Initialize the pragma handlers. PragmaHandlers = new PragmaNamespace(llvm::StringRef()); @@ -96,6 +97,23 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts, // Initialize builtin macros like __LINE__ and friends. RegisterBuiltinMacros(); + + if(Features.Borland) { + Ident__exception_info = getIdentifierInfo("_exception_info"); + Ident___exception_info = getIdentifierInfo("__exception_info"); + Ident_GetExceptionInfo = getIdentifierInfo("GetExceptionInformation"); + Ident__exception_code = getIdentifierInfo("_exception_code"); + Ident___exception_code = getIdentifierInfo("__exception_code"); + Ident_GetExceptionCode = getIdentifierInfo("GetExceptionCode"); + Ident__abnormal_termination = getIdentifierInfo("_abnormal_termination"); + Ident___abnormal_termination = getIdentifierInfo("__abnormal_termination"); + Ident_AbnormalTermination = getIdentifierInfo("AbnormalTermination"); + } else { + Ident__exception_info = Ident__exception_code = Ident__abnormal_termination = 0; + Ident___exception_info = Ident___exception_code = Ident___abnormal_termination = 0; + Ident_GetExceptionInfo = Ident_GetExceptionCode = Ident_AbnormalTermination = 0; + } + } Preprocessor::~Preprocessor() { @@ -399,6 +417,34 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const { return II; } +void Preprocessor::SetPoisonReason(IdentifierInfo *II, unsigned DiagID) { + PoisonReasons[II] = DiagID; +} + +void Preprocessor::PoisonSEHIdentifiers(bool Poison) { + assert(Ident__exception_code && Ident__exception_info); + assert(Ident___exception_code && Ident___exception_info); + Ident__exception_code->setIsPoisoned(Poison); + Ident___exception_code->setIsPoisoned(Poison); + Ident_GetExceptionCode->setIsPoisoned(Poison); + Ident__exception_info->setIsPoisoned(Poison); + Ident___exception_info->setIsPoisoned(Poison); + Ident_GetExceptionInfo->setIsPoisoned(Poison); + Ident__abnormal_termination->setIsPoisoned(Poison); + Ident___abnormal_termination->setIsPoisoned(Poison); + Ident_AbnormalTermination->setIsPoisoned(Poison); +} + +void Preprocessor::HandlePoisonedIdentifier(Token & Identifier) { + assert(Identifier.getIdentifierInfo() && + "Can't handle identifiers without identifier info!"); + llvm::DenseMap<IdentifierInfo*,unsigned>::const_iterator it = + PoisonReasons.find(Identifier.getIdentifierInfo()); + if(it == PoisonReasons.end()) + Diag(Identifier, diag::err_pp_used_poisoned_id); + else + Diag(Identifier,it->second) << Identifier.getIdentifierInfo(); +} /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier. This callback looks up the identifier in the map and/or @@ -417,10 +463,7 @@ void Preprocessor::HandleIdentifier(Token &Identifier) { // If this identifier was poisoned, and if it was not produced from a macro // expansion, emit an error. if (II.isPoisoned() && CurPPLexer) { - if (&II != Ident__VA_ARGS__) // We warn about __VA_ARGS__ with poisoning. - Diag(Identifier, diag::err_pp_used_poisoned_id); - else - Diag(Identifier, diag::ext_pp_bad_vaargs_use); + HandlePoisonedIdentifier(Identifier); } // If this is a macro to be expanded, do it. diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index f1e1596789..65aff0d1d0 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -367,11 +367,7 @@ void TokenLexer::Lex(Token &Tok) { // won't be handled by Preprocessor::HandleIdentifier because this is coming // from a macro expansion. if (II->isPoisoned() && TokenIsFromPaste) { - // We warn about __VA_ARGS__ with poisoning. - if (II->isStr("__VA_ARGS__")) - PP.Diag(Tok, diag::ext_pp_bad_vaargs_use); - else - PP.Diag(Tok, diag::err_pp_used_poisoned_id); + PP.HandlePoisonedIdentifier(Tok); } if (!DisableMacroExpansion && II->isHandleIdentifierCase()) diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index c41798e35e..92cdfffdc0 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1915,6 +1915,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'"); + // Poison the SEH identifiers so they are flagged as illegal in constructor initializers + PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); SourceLocation ColonLoc = ConsumeToken(); llvm::SmallVector<CXXCtorInitializer*, 4> MemInitializers; diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 07cef5597b..3741ccbca1 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -40,6 +40,7 @@ using namespace clang; /// jump-statement /// [C++] declaration-statement /// [C++] try-block +/// [MS] seh-try-block /// [OBC] objc-throw-statement /// [OBC] objc-try-catch-statement /// [OBC] objc-synchronized-statement @@ -272,6 +273,9 @@ Retry: case tok::kw_try: // C++ 15: try-block return ParseCXXTryBlock(attrs); + + case tok::kw___try: + return ParseSEHTryBlock(attrs); } // If we reached this code, the statement must end in a semicolon. @@ -321,7 +325,106 @@ StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get())); +} +StmtResult Parser::ParseSEHTryBlock(ParsedAttributes & Attrs) { + assert(Tok.is(tok::kw___try) && "Expected '__try'"); + SourceLocation Loc = ConsumeToken(); + return ParseSEHTryBlockCommon(Loc); +} + +/// ParseSEHTryBlockCommon +/// +/// seh-try-block: +/// '__try' compound-statement seh-handler +/// +/// seh-handler: +/// seh-except-block +/// seh-finally-block +/// +StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { + if(Tok.isNot(tok::l_brace)) + return StmtError(Diag(Tok,diag::err_expected_lbrace)); + + ParsedAttributesWithRange attrs(AttrFactory); + StmtResult TryBlock(ParseCompoundStatement(attrs)); + if(TryBlock.isInvalid()) + return move(TryBlock); + + StmtResult Handler; + if(Tok.is(tok::kw___except)) { + SourceLocation Loc = ConsumeToken(); + Handler = ParseSEHExceptBlock(Loc); + } else if (Tok.is(tok::kw___finally)) { + SourceLocation Loc = ConsumeToken(); + Handler = ParseSEHFinallyBlock(Loc); + } else { + return StmtError(Diag(Tok,diag::err_seh_expected_handler)); + } + + if(Handler.isInvalid()) + return move(Handler); + + return Actions.ActOnSEHTryBlock(false /* IsCXXTry */, + TryLoc, + TryBlock.take(), + Handler.take()); +} + +/// ParseSEHExceptBlock - Handle __except +/// +/// seh-except-block: +/// '__except' '(' seh-filter-expression ')' compound-statement +/// +StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { + PoisonIdentifierRAIIObject raii(Ident__exception_code, false), + raii2(Ident___exception_code, false), + raii3(Ident_GetExceptionCode, false); + + if(ExpectAndConsume(tok::l_paren,diag::err_expected_lparen)) + return StmtError(); + + ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope); + + Ident__exception_info->setIsPoisoned(false); + Ident___exception_info->setIsPoisoned(false); + Ident_GetExceptionInfo->setIsPoisoned(false); + ExprResult FilterExpr(ParseExpression()); + Ident__exception_info->setIsPoisoned(true); + Ident___exception_info->setIsPoisoned(true); + Ident_GetExceptionInfo->setIsPoisoned(true); + + if(FilterExpr.isInvalid()) + return StmtError(); + + if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen)) + return StmtError(); + + ParsedAttributesWithRange attrs(AttrFactory); + StmtResult Block(ParseCompoundStatement(attrs)); + + if(Block.isInvalid()) + return move(Block); + + return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.take(), Block.take()); +} + +/// ParseSEHFinallyBlock - Handle __finally +/// +/// seh-finally-block: +/// '__finally' compound-statement +/// +StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) { + PoisonIdentifierRAIIObject raii(Ident__abnormal_termination, false), + raii2(Ident___abnormal_termination, false), + raii3(Ident_AbnormalTermination, false); + + ParsedAttributesWithRange attrs(AttrFactory); + StmtResult Block(ParseCompoundStatement(attrs)); + if(Block.isInvalid()) + return move(Block); + + return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.take()); } /// ParseLabeledStatement - We have an identifier and a ':' after it. @@ -1786,6 +1889,10 @@ StmtResult Parser::ParseCXXTryBlock(ParsedAttributes &attrs) { /// handler-seq: /// handler handler-seq[opt] /// +/// [Borland] try-block: +/// 'try' compound-statement seh-except-block +/// 'try' compound-statment seh-finally-block +/// StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { if (Tok.isNot(tok::l_brace)) return StmtError(Diag(Tok, diag::err_expected_lbrace)); @@ -1795,23 +1902,45 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { if (TryBlock.isInvalid()) return move(TryBlock); - StmtVector Handlers(Actions); - MaybeParseCXX0XAttributes(attrs); - ProhibitAttributes(attrs); - - if (Tok.isNot(tok::kw_catch)) - return StmtError(Diag(Tok, diag::err_expected_catch)); - while (Tok.is(tok::kw_catch)) { - StmtResult Handler(ParseCXXCatchBlock()); - if (!Handler.isInvalid()) - Handlers.push_back(Handler.release()); + // Borland allows SEH-handlers with 'try' + if(Tok.is(tok::kw___except) || Tok.is(tok::kw___finally)) { + // TODO: Factor into common return ParseSEHHandlerCommon(...) + StmtResult Handler; + if(Tok.is(tok::kw___except)) { + SourceLocation Loc = ConsumeToken(); + Handler = ParseSEHExceptBlock(Loc); + } + else { + SourceLocation Loc = ConsumeToken(); + Handler = ParseSEHFinallyBlock(Loc); + } + if(Handler.isInvalid()) + return move(Handler); + + return Actions.ActOnSEHTryBlock(true /* IsCXXTry */, + TryLoc, + TryBlock.take(), + Handler.take()); } - // Don't bother creating the full statement if we don't have any usable - // handlers. - if (Handlers.empty()) - return StmtError(); + else { + StmtVector Handlers(Actions); + MaybeParseCXX0XAttributes(attrs); + ProhibitAttributes(attrs); - return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), move_arg(Handlers)); + if (Tok.isNot(tok::kw_catch)) + return StmtError(Diag(Tok, diag::err_expected_catch)); + while (Tok.is(tok::kw_catch)) { + StmtResult Handler(ParseCXXCatchBlock()); + if (!Handler.isInvalid()) + Handlers.push_back(Handler.release()); + } + // Don't bother creating the full statement if we don't have any usable + // handlers. + if (Handlers.empty()) + return StmtError(); + + return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), move_arg(Handlers)); + } } /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index ee4ef4263a..4d08699bdd 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -438,6 +438,32 @@ void Parser::Initialize() { Ident_deprecated = 0; Ident_obsoleted = 0; Ident_unavailable = 0; + + Ident__exception_code = Ident__exception_info = Ident__abnormal_termination = 0; + Ident___exception_code = Ident___exception_info = Ident___abnormal_termination = 0; + Ident_GetExceptionCode = Ident_GetExceptionInfo = Ident_AbnormalTermination = 0; + + if(getLang().Borland) { + Ident__exception_info = PP.getIdentifierInfo("_exception_info"); + Ident___exception_info = PP.getIdentifierInfo("__exception_info"); + Ident_GetExceptionInfo = PP.getIdentifierInfo("GetExceptionInformation"); + Ident__exception_code = PP.getIdentifierInfo("_exception_code"); + Ident___exception_code = PP.getIdentifierInfo("__exception_code"); + Ident_GetExceptionCode = PP.getIdentifierInfo("GetExceptionCode"); + Ident__abnormal_termination = PP.getIdentifierInfo("_abnormal_termination"); + Ident___abnormal_termination = PP.getIdentifierInfo("__abnormal_termination"); + Ident_AbnormalTermination = PP.getIdentifierInfo("AbnormalTermination"); + + PP.SetPoisonReason(Ident__exception_code,diag::err_seh___except_block); + PP.SetPoisonReason(Ident___exception_code,diag::err_seh___except_block); + PP.SetPoisonReason(Ident_GetExceptionCode,diag::err_seh___except_block); + PP.SetPoisonReason(Ident__exception_info,diag::err_seh___except_filter); + PP.SetPoisonReason(Ident___exception_info,diag::err_seh___except_filter); + PP.SetPoisonReason(Ident_GetExceptionInfo,diag::err_seh___except_filter); + PP.SetPoisonReason(Ident__abnormal_termination,diag::err_seh___finally_block); + PP.SetPoisonReason(Ident___abnormal_termination,diag::err_seh___finally_block); + PP.SetPoisonReason(Ident_AbnormalTermination,diag::err_seh___finally_block); + } } /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the @@ -766,6 +792,8 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs, /// Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo) { + // Poison the SEH identifiers so they are flagged as illegal in function bodies + PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // If this is C90 and the declspecs were completely missing, fudge in an diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h index 583f18428d..3765f92348 100644 --- a/lib/Parse/RAIIObjectsForParser.h +++ b/lib/Parse/RAIIObjectsForParser.h @@ -112,7 +112,31 @@ namespace clang { P.BraceCount = BraceCount; } }; - + + class PoisonSEHIdentifiersRAIIObject { + PoisonIdentifierRAIIObject Ident_AbnormalTermination; + PoisonIdentifierRAIIObject Ident_GetExceptionCode; + PoisonIdentifierRAIIObject Ident_GetExceptionInfo; + PoisonIdentifierRAIIObject Ident__abnormal_termination; + PoisonIdentifierRAIIObject Ident__exception_code; + PoisonIdentifierRAIIObject Ident__exception_info; + PoisonIdentifierRAIIObject Ident___abnormal_termination; + PoisonIdentifierRAIIObject Ident___exception_code; + PoisonIdentifierRAIIObject Ident___exception_info; + public: + PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue) + : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue), + Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue), + Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue), + Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue), + Ident__exception_code(Self.Ident__exception_code, NewValue), + Ident__exception_info(Self.Ident__exception_info, NewValue), + Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue), + Ident___exception_code(Self.Ident___exception_code, NewValue), + Ident___exception_info(Self.Ident___exception_info, NewValue) { + } + }; + } // end namespace clang #endif diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 38f3bf9e92..65cea7a69d 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2231,3 +2231,36 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers, NumHandlers)); } + +StmtResult +Sema::ActOnSEHTryBlock(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { + assert(TryBlock && Handler); + + getCurFunction()->setHasBranchProtectedScope(); + + return Owned(SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler)); +} + +StmtResult +Sema::ActOnSEHExceptBlock(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) { + assert(FilterExpr && Block); + + if(!FilterExpr->getType()->isIntegerType()) { + return StmtError(Diag(FilterExpr->getExprLoc(), diag::err_filter_expression_integral) << FilterExpr->getType()); + } + + return Owned(SEHExceptStmt::Create(Context,Loc,FilterExpr,Block)); +} + +StmtResult +Sema::ActOnSEHFinallyBlock(SourceLocation Loc, + Stmt *Block) { + assert(Block); + return Owned(SEHFinallyStmt::Create(Context,Loc,Block)); +} + diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index f5ec3a2170..9f38f2aa3d 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -490,6 +490,9 @@ public: QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T); #include "clang/AST/TypeLocNodes.def" + StmtResult + TransformSEHHandler(Stmt *Handler); + QualType TransformTemplateSpecializationType(TypeLocBuilder &TLB, TemplateSpecializationTypeLoc TL, @@ -1254,6 +1257,24 @@ public: return getSema().FinishCXXForRangeStmt(ForRange, Body); } + StmtResult RebuildSEHTryStmt(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { + return getSema().ActOnSEHTryBlock(IsCXXTry,TryLoc,TryBlock,Handler); + } + + StmtResult RebuildSEHExceptStmt(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) { + return getSema().ActOnSEHExceptBlock(Loc,FilterExpr,Block); + } + + StmtResult RebuildSEHFinallyStmt(SourceLocation Loc, + Stmt *Block) { + return getSema().ActOnSEHFinallyBlock(Loc,Block); + } + /// \brief Build a new expression that references a declaration. /// /// By default, performs semantic analysis to build the new expression. @@ -5471,6 +5492,57 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { return FinishCXXForRangeStmt(NewStmt.get(), Body.get()); } +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) { + StmtResult TryBlock; // = getDerived().TransformCompoundStmt(S->getTryBlock()); + if(TryBlock.isInvalid()) return StmtError(); + + StmtResult Handler = getDerived().TransformSEHHandler(S->getHandler()); + if(!getDerived().AlwaysRebuild() && + TryBlock.get() == S->getTryBlock() && + Handler.get() == S->getHandler()) + return SemaRef.Owned(S); + + return getDerived().RebuildSEHTryStmt(S->getIsCXXTry(), + S->getTryLoc(), + TryBlock.take(), + Handler.take()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHFinallyStmt(SEHFinallyStmt *S) { + StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock()); + if(Block.isInvalid()) return StmtError(); + + return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(), + Block.take()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHExceptStmt(SEHExceptStmt *S) { + ExprResult FilterExpr = getDerived().TransformExpr(S->getFilterExpr()); + if(FilterExpr.isInvalid()) return StmtError(); + + StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock()); + if(Block.isInvalid()) return StmtError(); + + return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(), + FilterExpr.take(), + Block.take()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) { + if(isa<SEHFinallyStmt>(Handler)) + return getDerived().TransformSEHFinallyStmt(cast<SEHFinallyStmt>(Handler)); + else + return getDerived().TransformSEHExceptStmt(cast<SEHExceptStmt>(Handler)); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 5c1dfb80ec..657420d06f 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -442,6 +442,9 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, case Stmt::CXXNoexceptExprClass: case Stmt::PackExpansionExprClass: case Stmt::SubstNonTypeTemplateParmPackExprClass: + case Stmt::SEHTryStmtClass: + case Stmt::SEHExceptStmtClass: + case Stmt::SEHFinallyStmtClass: { SaveAndRestore<bool> OldSink(Builder->BuildSinks); Builder->BuildSinks = true; |