aboutsummaryrefslogtreecommitdiff
path: root/include/clang
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 /include/clang
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 'include/clang')
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h4
-rw-r--r--include/clang/AST/Stmt.h116
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td12
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--include/clang/Basic/IdentifierTable.h19
-rw-r--r--include/clang/Basic/StmtNodes.td3
-rw-r--r--include/clang/Lex/Preprocessor.h32
-rw-r--r--include/clang/Parse/Parser.h18
-rw-r--r--include/clang/Sema/Sema.h13
9 files changed, 219 insertions, 1 deletions
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 28daf51dd9..9edc7de114 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1933,6 +1933,10 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
}
})
+DEF_TRAVERSE_STMT(SEHTryStmt, {})
+DEF_TRAVERSE_STMT(SEHExceptStmt, {})
+DEF_TRAVERSE_STMT(SEHFinallyStmt,{})
+
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { })
DEF_TRAVERSE_STMT(OpaqueValueExpr, { })
DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { })
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 3bbe6ce510..b368523eef 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -1435,6 +1435,122 @@ public:
}
};
+class SEHExceptStmt : public Stmt {
+ SourceLocation Loc;
+ Stmt *Children[2];
+
+ enum { FILTER_EXPR, BLOCK };
+
+ SEHExceptStmt(SourceLocation Loc,
+ Expr *FilterExpr,
+ Stmt *Block);
+
+public:
+ static SEHExceptStmt* Create(ASTContext &C,
+ SourceLocation ExceptLoc,
+ Expr *FilterExpr,
+ Stmt *Block);
+ SourceRange getSourceRange() const {
+ return SourceRange(getExceptLoc(), getEndLoc());
+ }
+
+ SourceLocation getExceptLoc() const { return Loc; }
+ SourceLocation getEndLoc() const { return getBlock()->getLocEnd(); }
+
+ Expr *getFilterExpr() const { return reinterpret_cast<Expr*>(Children[FILTER_EXPR]); }
+ CompoundStmt *getBlock() const { return llvm::cast<CompoundStmt>(Children[BLOCK]); }
+
+ child_range children() {
+ return child_range(Children,Children+2);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SEHExceptStmtClass;
+ }
+
+ static bool classof(SEHExceptStmt *) { return true; }
+
+};
+
+class SEHFinallyStmt : public Stmt {
+ SourceLocation Loc;
+ Stmt *Block;
+
+ SEHFinallyStmt(SourceLocation Loc,
+ Stmt *Block);
+
+public:
+ static SEHFinallyStmt* Create(ASTContext &C,
+ SourceLocation FinallyLoc,
+ Stmt *Block);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getFinallyLoc(), getEndLoc());
+ }
+
+ SourceLocation getFinallyLoc() const { return Loc; }
+ SourceLocation getEndLoc() const { return Block->getLocEnd(); }
+
+ CompoundStmt *getBlock() const { return llvm::cast<CompoundStmt>(Block); }
+
+ child_range children() {
+ return child_range(&Block,&Block+1);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SEHFinallyStmtClass;
+ }
+
+ static bool classof(SEHFinallyStmt *) { return true; }
+
+};
+
+class SEHTryStmt : public Stmt {
+ bool IsCXXTry;
+ SourceLocation TryLoc;
+ Stmt *Children[2];
+
+ enum { TRY = 0, HANDLER = 1 };
+
+ SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try'
+ SourceLocation TryLoc,
+ Stmt *TryBlock,
+ Stmt *Handler);
+
+public:
+ static SEHTryStmt* Create(ASTContext &C,
+ bool isCXXTry,
+ SourceLocation TryLoc,
+ Stmt *TryBlock,
+ Stmt *Handler);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getTryLoc(), getEndLoc());
+ }
+
+ SourceLocation getTryLoc() const { return TryLoc; }
+ SourceLocation getEndLoc() const { return Children[HANDLER]->getLocEnd(); }
+
+ bool getIsCXXTry() const { return IsCXXTry; }
+ CompoundStmt* getTryBlock() const { return llvm::cast<CompoundStmt>(Children[TRY]); }
+ Stmt *getHandler() const { return Children[HANDLER]; }
+
+ /// Returns 0 if not defined
+ SEHExceptStmt *getExceptHandler() const;
+ SEHFinallyStmt *getFinallyHandler() const;
+
+ child_range children() {
+ return child_range(Children,Children+2);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SEHTryStmtClass;
+ }
+
+ static bool classof(SEHTryStmt *) { return true; }
+
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index ccd48daca6..c37e510b34 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -521,5 +521,17 @@ def warn_pragma_expected_enable_disable : Warning<
def warn_pragma_unknown_extension : Warning<
"unknown OpenCL extension %0 - ignoring">;
+def err_seh_expected_handler : Error<
+ "expected '__except' or '__finally' block">;
+
+def err_seh___except_block : Error<
+ "%0 only allowed in __except block">;
+
+def err_seh___except_filter : Error<
+ "%0 only allowed in __except filter expression">;
+
+def err_seh___finally_block : Error<
+ "%0 only allowed in __finally block">;
+
} // end of Parse Issue category.
} // end of Parser diagnostics
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 8c863c2d1d..6c8471b363 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3946,6 +3946,9 @@ def err_unknown_any_addrof : Error<
def err_unknown_any_var_function_type : Error<
"variable %0 with unknown type cannot be given a function type">;
+def err_filter_expression_integral : Error<
+ "filter expression type should be an integral value not %0">;
+
} // end of sema category
} // end of sema component.
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 5e5097df15..683ec8312e 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -255,6 +255,25 @@ private:
}
};
+/// \brief an RAII object for [un]poisoning an identifier
+/// within a certain scope. II is allowed to be null, in
+/// which case, objects of this type have no effect.
+class PoisonIdentifierRAIIObject {
+ IdentifierInfo *const II;
+ const bool OldValue;
+public:
+ PoisonIdentifierRAIIObject(IdentifierInfo *II, bool NewValue)
+ : II(II), OldValue(II ? II->isPoisoned() : false) {
+ if(II)
+ II->setIsPoisoned(NewValue);
+ }
+
+ ~PoisonIdentifierRAIIObject() {
+ if(II)
+ II->setIsPoisoned(OldValue);
+ }
+};
+
/// \brief An iterator that walks over all of the known identifiers
/// in the lookup table.
///
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index d87d14ff53..15ac760ce7 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -142,4 +142,7 @@ def OpaqueValueExpr : DStmt<Expr>;
// Microsoft Extensions.
def CXXUuidofExpr : DStmt<Expr>;
+def SEHTryStmt : Stmt;
+def SEHExceptStmt : Stmt;
+def SEHFinallyStmt : Stmt;
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 86f9c43c3f..616507a914 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -783,6 +783,38 @@ public:
/// updating the token kind accordingly.
IdentifierInfo *LookUpIdentifierInfo(Token &Identifier) const;
+private:
+ llvm::DenseMap<IdentifierInfo*,unsigned> PoisonReasons;
+
+public:
+
+ // SetPoisonReason - Call this function to indicate the reason for
+ // poisoning an identifier. If that identifier is accessed while
+ // poisoned, then this reason will be used instead of the default
+ // "poisoned" diagnostic.
+ void SetPoisonReason(IdentifierInfo *II, unsigned DiagID);
+
+ // HandlePoisonedIdentifier - Display reason for poisoned
+ // identifier.
+ void HandlePoisonedIdentifier(Token & Tok);
+
+ void MaybeHandlePoisonedIdentifier(Token & Identifier) {
+ if(IdentifierInfo * II = Identifier.getIdentifierInfo()) {
+ if(II->isPoisoned()) {
+ HandlePoisonedIdentifier(Identifier);
+ }
+ }
+ }
+
+private:
+ /// Identifiers used for SEH handling in Borland. These are only
+ /// allowed in particular circumstances
+ IdentifierInfo *Ident__exception_code, *Ident___exception_code, *Ident_GetExceptionCode; // __except block
+ IdentifierInfo *Ident__exception_info, *Ident___exception_info, *Ident_GetExceptionInfo; // __except filter expression
+ IdentifierInfo *Ident__abnormal_termination, *Ident___abnormal_termination, *Ident_AbnormalTermination; // __finally
+public:
+ void PoisonSEHIdentifiers(bool Poison = true); // Borland
+
/// HandleIdentifier - This callback is invoked when the lexer reads an
/// identifier and has filled in the tokens IdentifierInfo member. This
/// callback potentially macro expands it or turns it into a named token (like
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index cda9a61b33..3fd9844368 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -32,8 +32,9 @@ namespace clang {
class PragmaUnusedHandler;
class ColonProtectionRAIIObject;
class InMessageExpressionRAIIObject;
+ class PoisonSEHIdentifiersRAIIObject;
class VersionTuple;
-
+
/// PrettyStackTraceParserEntry - If a crash happens while the parser is active,
/// an entry is printed for it.
class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
@@ -75,6 +76,7 @@ class Parser : public CodeCompletionHandler {
friend class PragmaUnusedHandler;
friend class ColonProtectionRAIIObject;
friend class InMessageExpressionRAIIObject;
+ friend class PoisonSEHIdentifiersRAIIObject;
friend class ParenBraceBracketBalancer;
Preprocessor &PP;
@@ -102,6 +104,12 @@ class Parser : public CodeCompletionHandler {
unsigned NumCachedScopes;
Scope *ScopeCache[ScopeCacheSize];
+ /// Identifiers used for SEH handling in Borland. These are only
+ /// allowed in particular circumstances
+ IdentifierInfo *Ident__exception_code, *Ident___exception_code, *Ident_GetExceptionCode; // __except block
+ IdentifierInfo *Ident__exception_info, *Ident___exception_info, *Ident_GetExceptionInfo; // __except filter expression
+ IdentifierInfo *Ident__abnormal_termination, *Ident___abnormal_termination, *Ident_AbnormalTermination; // __finally
+
/// Ident_super - IdentifierInfo for "super", to support fast
/// comparison.
IdentifierInfo *Ident_super;
@@ -1312,6 +1320,14 @@ private:
StmtResult ParseCXXCatchBlock();
//===--------------------------------------------------------------------===//
+ // MS: SEH Statements and Blocks
+
+ StmtResult ParseSEHTryBlock(ParsedAttributes &Attr);
+ StmtResult ParseSEHTryBlockCommon(SourceLocation Loc);
+ StmtResult ParseSEHExceptBlock(SourceLocation Loc);
+ StmtResult ParseSEHFinallyBlock(SourceLocation Loc);
+
+ //===--------------------------------------------------------------------===//
// Objective-C Statements
StmtResult ParseObjCAtStatement(SourceLocation atLoc);
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 72878de047..0744ced9e9 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2001,6 +2001,19 @@ public:
Decl *ExDecl, Stmt *HandlerBlock);
StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
MultiStmtArg Handlers);
+
+ StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ?
+ SourceLocation TryLoc,
+ Stmt *TryBlock,
+ Stmt *Handler);
+
+ StmtResult ActOnSEHExceptBlock(SourceLocation Loc,
+ Expr *FilterExpr,
+ Stmt *Block);
+
+ StmtResult ActOnSEHFinallyBlock(SourceLocation Loc,
+ Stmt *Block);
+
void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;