aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@boostpro.com>2011-04-28 01:08:34 +0000
committerJohn Wiegley <johnw@boostpro.com>2011-04-28 01:08:34 +0000
commit28bbe4b8acc338476fe0825769b41fb32b423c72 (patch)
tree93a24e53fba644d6caa1db0b82cd678ef8fb0f8d /lib/Parse
parent61d0b6baf47cf411f6c0f6ddb4acffcfeec724f1 (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/Parse')
-rw-r--r--lib/Parse/ParseDeclCXX.cpp2
-rw-r--r--lib/Parse/ParseStmt.cpp159
-rw-r--r--lib/Parse/Parser.cpp28
-rw-r--r--lib/Parse/RAIIObjectsForParser.h26
4 files changed, 199 insertions, 16 deletions
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