[cfe-commits] r70155 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/Analysis/ lib/CodeGen/ lib/Parse/ lib/Sema/ test/Parser/ tools/clang-cc/
Sebastian Redl
sebastian.redl at getdesigned.at
Sun Apr 26 13:35:06 PDT 2009
Author: cornedbee
Date: Sun Apr 26 15:35:05 2009
New Revision: 70155
URL: http://llvm.org/viewvc/llvm-project?rev=70155&view=rev
Log:
Implement function-try-blocks. However, there's a very subtle bug that I can't track down.
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/DeclBase.h
cfe/trunk/include/clang/AST/DeclObjC.h
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/DeclBase.cpp
cfe/trunk/lib/Analysis/BugReporter.cpp
cfe/trunk/lib/Analysis/CFRefCount.cpp
cfe/trunk/lib/Analysis/PathDiagnostic.cpp
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/Parser/cxx-try.cpp
cfe/trunk/tools/clang-cc/RewriteBlocks.cpp
cfe/trunk/tools/clang-cc/RewriteObjC.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sun Apr 26 15:35:05 2009
@@ -554,17 +554,16 @@
/// function. The variant that accepts a FunctionDecl pointer will
/// set that function declaration to the actual declaration
/// containing the body (if there is one).
- CompoundStmt *getBody(ASTContext &Context,
- const FunctionDecl *&Definition) const;
+ Stmt *getBody(ASTContext &Context, const FunctionDecl *&Definition) const;
- virtual CompoundStmt *getBody(ASTContext &Context) const {
+ virtual Stmt *getBody(ASTContext &Context) const {
const FunctionDecl* Definition;
return getBody(Context, Definition);
}
/// \brief If the function has a body that is immediately available,
/// return it.
- CompoundStmt *getBodyIfAvailable() const;
+ Stmt *getBodyIfAvailable() const;
/// isThisDeclarationADefinition - Returns whether this specific
/// declaration of the function is also a definition. This does not
@@ -574,7 +573,7 @@
/// CodeGenModule.cpp uses it, and I don't know if this would break it.
bool isThisDeclarationADefinition() const { return Body; }
- void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
+ void setBody(Stmt *B) { Body = B; }
void setLazyBody(uint64_t Offset) { Body = Offset; }
/// Whether this function is virtual, either by explicit marking, or by
@@ -1148,7 +1147,7 @@
SourceLocation getCaretLocation() const { return getLocation(); }
CompoundStmt *getBody() const { return (CompoundStmt*) Body; }
- CompoundStmt *getBody(ASTContext &C) const { return (CompoundStmt*) Body; }
+ Stmt *getBody(ASTContext &C) const { return (Stmt*) Body; }
void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
// Iterator access to formal parameters.
Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Sun Apr 26 15:35:05 2009
@@ -281,11 +281,18 @@
// be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const;
- // getBody - If this Decl represents a declaration for a body of code,
- // such as a function or method definition, this method returns the top-level
- // Stmt* of that body. Otherwise this method returns null.
- virtual CompoundStmt* getBody(ASTContext &Context) const { return 0; }
-
+ /// getBody - If this Decl represents a declaration for a body of code,
+ /// such as a function or method definition, this method returns the
+ /// top-level Stmt* of that body. Otherwise this method returns null.
+ virtual Stmt* getBody(ASTContext &Context) const { return 0; }
+
+ /// getCompoundBody - Returns getBody(), dyn_casted to a CompoundStmt.
+ CompoundStmt* getCompoundBody(ASTContext &Context) const;
+
+ /// getBodyRBrace - Gets the right brace of the body, if a body exists.
+ /// This works whether the body is a CompoundStmt or a CXXTryStmt.
+ SourceLocation getBodyRBrace(ASTContext &Context) const;
+
// global temp stats (until we have a per-module visitor)
static void addDeclKind(Kind k);
static bool CollectingStats(bool Enable = false);
Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Sun Apr 26 15:35:05 2009
@@ -242,11 +242,11 @@
return ImplementationControl(DeclImplementation);
}
- virtual CompoundStmt *getBody(ASTContext &C) const {
- return (CompoundStmt*) Body;
+ virtual Stmt *getBody(ASTContext &C) const {
+ return (Stmt*) Body;
}
CompoundStmt *getBody() { return (CompoundStmt*)Body; }
- void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
+ void setBody(Stmt *B) { Body = B; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; }
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sun Apr 26 15:35:05 2009
@@ -205,6 +205,7 @@
def ext_ellipsis_exception_spec : Extension<
"exception specification of '...' is a Microsoft extension">;
def err_expected_catch : Error<"expected catch">;
+def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sun Apr 26 15:35:05 2009
@@ -795,6 +795,7 @@
// C++ 6: Statements and Blocks
OwningStmtResult ParseCXXTryBlock();
+ OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
OwningStmtResult ParseCXXCatchBlock();
//===--------------------------------------------------------------------===//
@@ -815,7 +816,8 @@
bool RequireSemi = true);
DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
-
+ DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl);
+
bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
TemplateParameterLists *TemplateParams,
AccessSpecifier AS);
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sun Apr 26 15:35:05 2009
@@ -321,22 +321,22 @@
}
-CompoundStmt *FunctionDecl::getBody(ASTContext &Context,
- const FunctionDecl *&Definition) const {
+Stmt *FunctionDecl::getBody(ASTContext &Context,
+ const FunctionDecl *&Definition) const {
for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
if (FD->Body) {
Definition = FD;
- return cast<CompoundStmt>(FD->Body.get(Context.getExternalSource()));
+ return FD->Body.get(Context.getExternalSource());
}
}
return 0;
}
-CompoundStmt *FunctionDecl::getBodyIfAvailable() const {
+Stmt *FunctionDecl::getBodyIfAvailable() const {
for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
if (FD->Body && !FD->Body.isOffset()) {
- return cast<CompoundStmt>(FD->Body.get(0));
+ return FD->Body.get(0);
}
}
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Sun Apr 26 15:35:05 2009
@@ -20,6 +20,8 @@
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -341,6 +343,21 @@
}
}
+CompoundStmt* Decl::getCompoundBody(ASTContext &Context) const {
+ return dyn_cast_or_null<CompoundStmt>(getBody(Context));
+}
+
+SourceLocation Decl::getBodyRBrace(ASTContext &Context) const {
+ Stmt *Body = getBody(Context);
+ if (!Body)
+ return SourceLocation();
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
+ return CS->getRBracLoc();
+ assert(isa<CXXTryStmt>(Body) &&
+ "Body can only be CompoundStmt or CXXTryStmt");
+ return cast<CXXTryStmt>(Body)->getSourceRange().getEnd();
+}
+
#ifndef NDEBUG
void Decl::CheckAccessDeclContext() const {
assert((Access != AS_none || isa<TranslationUnitDecl>(this) ||
Modified: cfe/trunk/lib/Analysis/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BugReporter.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BugReporter.cpp (original)
+++ cfe/trunk/lib/Analysis/BugReporter.cpp Sun Apr 26 15:35:05 2009
@@ -189,7 +189,7 @@
if (Stmt *S = GetNextStmt(N))
return PathDiagnosticLocation(S, SMgr);
- return FullSourceLoc(CodeDecl.getBody(getContext())->getRBracLoc(), SMgr);
+ return FullSourceLoc(CodeDecl.getBodyRBrace(getContext()), SMgr);
}
PathDiagnosticLocation
@@ -825,7 +825,9 @@
// Finally, add an initial edge from the start location of the first
// statement (if it doesn't already exist).
- if (const CompoundStmt *CS = PDB.getCodeDecl().getBody(PDB.getContext()))
+ // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
+ if (const CompoundStmt *CS =
+ PDB.getCodeDecl().getCompoundBody(PDB.getContext()))
if (!CS->body_empty()) {
SourceLocation Loc = (*CS->body_begin())->getLocStart();
rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager()));
Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Sun Apr 26 15:35:05 2009
@@ -3047,11 +3047,11 @@
LeakN = LeakN->succ_empty() ? 0 : *(LeakN->succ_begin());
}
-
+
if (!L.isValid()) {
- CompoundStmt *CS
- = BR.getStateManager().getCodeDecl().getBody(BR.getContext());
- L = PathDiagnosticLocation(CS->getRBracLoc(), SMgr);
+ L = PathDiagnosticLocation(
+ BR.getStateManager().getCodeDecl().getBodyRBrace(BR.getContext()),
+ SMgr);
}
std::string sbuf;
Modified: cfe/trunk/lib/Analysis/PathDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PathDiagnostic.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PathDiagnostic.cpp (original)
+++ cfe/trunk/lib/Analysis/PathDiagnostic.cpp Sun Apr 26 15:35:05 2009
@@ -15,6 +15,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/StmtCXX.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Casting.h"
#include <sstream>
@@ -197,8 +198,12 @@
// FIXME: We would like to always get the function body, even
// when it needs to be de-serialized, but getting the
// ASTContext here requires significant changes.
- if (CompoundStmt *Body = FD->getBodyIfAvailable())
- return Body->getSourceRange();
+ if (Stmt *Body = FD->getBodyIfAvailable()) {
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
+ return CS->getSourceRange();
+ else
+ return cast<CXXTryStmt>(Body)->getSourceRange();
+ }
}
else {
SourceLocation L = D->getLocation();
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sun Apr 26 15:35:05 2009
@@ -129,7 +129,7 @@
DebugInfo = CGM.getDebugInfo();
StartObjCMethod(OMD, OMD->getClassInterface());
EmitStmt(OMD->getBody(getContext()));
- FinishFunction(cast<CompoundStmt>(OMD->getBody(getContext()))->getRBracLoc());
+ FinishFunction(OMD->getBodyRBrace(getContext()));
}
// FIXME: I wasn't sure about the synthesis approach. If we end up
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Sun Apr 26 15:35:05 2009
@@ -225,12 +225,13 @@
FProto->getArgType(i)));
}
- const CompoundStmt *S = FD->getBody(getContext());
+ // FIXME: Support CXXTryStmt here, too.
+ if (const CompoundStmt *S = FD->getCompoundBody(getContext())) {
+ StartFunction(FD, FD->getResultType(), Fn, Args, S->getLBracLoc());
+ EmitStmt(S);
+ FinishFunction(S->getRBracLoc());
+ }
- StartFunction(FD, FD->getResultType(), Fn, Args, S->getLBracLoc());
- EmitStmt(S);
- FinishFunction(S->getRBracLoc());
-
// Destroy the 'this' declaration.
if (CXXThisDecl)
CXXThisDecl->Destroy(getContext());
Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Sun Apr 26 15:35:05 2009
@@ -17,15 +17,15 @@
#include "clang/Parse/Scope.h"
using namespace clang;
-/// ParseInlineCXXMethodDef - We parsed and verified that the specified
+/// ParseCXXInlineMethodDef - We parsed and verified that the specified
/// Declarator is a well formed C++ inline method definition. Now lex its body
/// and store its tokens for parsing after the C++ class is complete.
Parser::DeclPtrTy
Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) {
assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
"This isn't a function declarator!");
- assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) &&
- "Current token not a '{' or ':'!");
+ assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
+ "Current token not a '{', ':' or 'try'!");
DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0);
@@ -34,8 +34,9 @@
getCurTopClassStack().MethodDefs.push_back(LexedMethod(FnD));
CachedTokens &Toks = getCurTopClassStack().MethodDefs.back().Toks;
- // We may have a constructor initializer here.
- if (Tok.is(tok::colon)) {
+ tok::TokenKind kind = Tok.getKind();
+ // We may have a constructor initializer or function-try-block here.
+ if (kind == tok::colon || kind == tok::kw_try) {
// Consume everything up to (and including) the left brace.
if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) {
// We didn't find the left-brace we expected after the
@@ -58,6 +59,14 @@
// Consume everything up to (and including) the matching right brace.
ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
+ // If we're in a function-try-block, we need to store all the catch blocks.
+ if (kind == tok::kw_try) {
+ while (Tok.is(tok::kw_catch)) {
+ ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks);
+ ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
+ }
+ }
+
return FnD;
}
@@ -126,14 +135,18 @@
// Consume the previously pushed token.
ConsumeAnyToken();
- assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) &&
- "Inline method not starting with '{' or ':'");
+ assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
+ && "Inline method not starting with '{', ':' or 'try'");
// Parse the method body. Function body parsing code is similar enough
// to be re-used for method bodies as well.
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
Actions.ActOnStartOfFunctionDef(CurScope, LM.D);
+ if (Tok.is(tok::kw_try)) {
+ ParseFunctionTryBlock(LM.D);
+ return;
+ }
if (Tok.is(tok::colon))
ParseConstructorInitializer(LM.D);
// FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'??
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sun Apr 26 15:35:05 2009
@@ -737,7 +737,8 @@
// function-definition:
if (Tok.is(tok::l_brace)
- || (DeclaratorInfo.isFunctionDeclarator() && Tok.is(tok::colon))) {
+ || (DeclaratorInfo.isFunctionDeclarator() &&
+ (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) {
if (!DeclaratorInfo.isFunctionDeclarator()) {
Diag(Tok, diag::err_func_def_no_params);
ConsumeBrace();
@@ -1044,6 +1045,7 @@
break;
else {
// Skip over garbage, until we get to '{'. Don't eat the '{'.
+ Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
SkipUntil(tok::l_brace, true, true);
break;
}
Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Sun Apr 26 15:35:05 2009
@@ -1289,7 +1289,7 @@
Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
assert(Tok.is(tok::l_brace));
SourceLocation LBraceLoc = Tok.getLocation();
-
+
PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions,
PP.getSourceManager(),
"parsing function body");
@@ -1307,18 +1307,58 @@
return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
}
+/// ParseFunctionTryBlock - Parse a C++ function-try-block.
+///
+/// function-try-block:
+/// 'try' ctor-initializer[opt] compound-statement handler-seq
+///
+Parser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) {
+ assert(Tok.is(tok::kw_try) && "Expected 'try'");
+ SourceLocation TryLoc = ConsumeToken();
+
+ PrettyStackTraceActionsDecl CrashInfo(Decl, TryLoc, Actions,
+ PP.getSourceManager(),
+ "parsing function try block");
+
+ // Constructor initializer list?
+ if (Tok.is(tok::colon))
+ ParseConstructorInitializer(Decl);
+
+ OwningStmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
+ // If we failed to parse the try-catch, we just give the function an empty
+ // compound statement as the body.
+ if (FnBody.isInvalid())
+ FnBody = Actions.ActOnCompoundStmt(TryLoc, TryLoc,
+ MultiStmtArg(Actions), false);
+
+ return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
+}
+
/// ParseCXXTryBlock - Parse a C++ try-block.
///
/// try-block:
/// 'try' compound-statement handler-seq
///
-/// handler-seq:
-/// handler handler-seq[opt]
-///
Parser::OwningStmtResult Parser::ParseCXXTryBlock() {
assert(Tok.is(tok::kw_try) && "Expected 'try'");
SourceLocation TryLoc = ConsumeToken();
+ return ParseCXXTryBlockCommon(TryLoc);
+}
+
+/// ParseCXXTryBlockCommon - Parse the common part of try-block and
+/// function-try-block.
+///
+/// try-block:
+/// 'try' compound-statement handler-seq
+///
+/// function-try-block:
+/// 'try' ctor-initializer[opt] compound-statement handler-seq
+///
+/// handler-seq:
+/// handler handler-seq[opt]
+///
+Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected_lbrace));
OwningStmtResult TryBlock(ParseCompoundStatement());
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Sun Apr 26 15:35:05 2009
@@ -536,7 +536,8 @@
(!getLang().CPlusPlus &&
isDeclarationSpecifier()) || // int X(f) int f; {}
(getLang().CPlusPlus &&
- Tok.is(tok::colon)))) { // X() : Base() {} (used for ctors)
+ (Tok.is(tok::colon) || // X() : Base() {} (used for ctors)
+ Tok.is(tok::kw_try))))) { // X() try { ... }
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
Diag(Tok, diag::err_function_declared_typedef);
@@ -575,7 +576,7 @@
/// decl-specifier-seq[opt] declarator ctor-initializer[opt]
/// function-body
/// [C++] function-definition: [C++ 8.4]
-/// decl-specifier-seq[opt] declarator function-try-block [TODO]
+/// decl-specifier-seq[opt] declarator function-try-block
///
Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D) {
const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
@@ -602,8 +603,8 @@
// We should have either an opening brace or, in a C++ constructor,
// we may have a colon.
- // FIXME: In C++, we might also find the 'try' keyword.
- if (Tok.isNot(tok::l_brace) && Tok.isNot(tok::colon)) {
+ if (Tok.isNot(tok::l_brace) && Tok.isNot(tok::colon) &&
+ Tok.isNot(tok::kw_try)) {
Diag(Tok, diag::err_expected_fn_body);
// Skip over garbage, until we get to '{'. Don't eat the '{'.
@@ -621,12 +622,14 @@
// specified Declarator for the function.
DeclPtrTy Res = Actions.ActOnStartOfFunctionDef(CurScope, D);
+ if (Tok.is(tok::kw_try))
+ return ParseFunctionTryBlock(Res);
+
// If we have a colon, then we're probably parsing a C++
// ctor-initializer.
if (Tok.is(tok::colon))
ParseConstructorInitializer(Res);
- SourceLocation BraceLoc = Tok.getLocation();
return ParseFunctionStatementBody(Res);
}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Apr 26 15:35:05 2009
@@ -18,6 +18,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/SourceManager.h"
@@ -2986,7 +2987,7 @@
Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) {
Decl *dcl = D.getAs<Decl>();
- CompoundStmt *Body =cast<CompoundStmt>(static_cast<Stmt*>(BodyArg.release()));
+ Stmt *Body = BodyArg.takeAs<Stmt>();
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) {
FD->setBody(Body);
assert(FD == getCurFunctionDecl() && "Function parsing confused");
@@ -3029,13 +3030,16 @@
// function somewhere so that it is properly owned and so that the goto
// has a valid target. Do this by creating a new compound stmt with the
// label in it.
-
+
// Give the label a sub-statement.
L->setSubStmt(new (Context) NullStmt(L->getIdentLoc()));
-
- std::vector<Stmt*> Elements(Body->body_begin(), Body->body_end());
+
+ CompoundStmt *Compound = isa<CXXTryStmt>(Body) ?
+ cast<CXXTryStmt>(Body)->getTryBlock() :
+ cast<CompoundStmt>(Body);
+ std::vector<Stmt*> Elements(Compound->body_begin(), Compound->body_end());
Elements.push_back(L);
- Body->setStmts(Context, &Elements[0], Elements.size());
+ Compound->setStmts(Context, &Elements[0], Elements.size());
}
FunctionLabelMap.clear();
Modified: cfe/trunk/test/Parser/cxx-try.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-try.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-try.cpp (original)
+++ cfe/trunk/test/Parser/cxx-try.cpp Sun Apr 26 15:35:05 2009
@@ -23,3 +23,22 @@
try {}
catch {} // expected-error {{expected '('}}
}
+
+void h() try {
+} catch(...) {
+}
+
+struct A {
+ int i;
+ A(float) : i(0) try {} // expected-error {{expected '{' or ','}}
+ A(int);
+ A(char);
+ // FIXME: There's something very strange going on here. After the first
+ // inline function-try-block, subsequent inline bodies aren't parsed anymore.
+ // Valgrind is silent, though, and I can't even debug this properly.
+ A() try : i(0) {} catch(...) {}
+ void f() try {} catch(...) {}
+};
+
+A::A(char) : i(0) try {} // expected-error {{expected '{' or ','}}
+A::A(int j) try : i(j) {} catch(...) {}
Modified: cfe/trunk/tools/clang-cc/RewriteBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/RewriteBlocks.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/tools/clang-cc/RewriteBlocks.cpp (original)
+++ cfe/trunk/tools/clang-cc/RewriteBlocks.cpp Sun Apr 26 15:35:05 2009
@@ -1091,8 +1091,9 @@
// prototype. This enables us to rewrite function declarations and
// definitions using the same code.
RewriteFunctionProtoType(FD->getType(), FD);
-
- if (CompoundStmt *Body = FD->getBody(*Context)) {
+
+ // FIXME: Handle CXXTryStmt
+ if (CompoundStmt *Body = FD->getCompoundBody(*Context)) {
CurFunctionDef = FD;
FD->setBody(cast_or_null<CompoundStmt>(RewriteFunctionBody(Body)));
// This synthesizes and inserts the block "impl" struct, invoke function,
Modified: cfe/trunk/tools/clang-cc/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/RewriteObjC.cpp?rev=70155&r1=70154&r2=70155&view=diff
==============================================================================
--- cfe/trunk/tools/clang-cc/RewriteObjC.cpp (original)
+++ cfe/trunk/tools/clang-cc/RewriteObjC.cpp Sun Apr 26 15:35:05 2009
@@ -980,8 +980,8 @@
ObjCMethodDecl *OMD = *I;
RewriteObjCMethodDecl(OMD, ResultStr);
SourceLocation LocStart = OMD->getLocStart();
- SourceLocation LocEnd = OMD->getBody(*Context)->getLocStart();
-
+ SourceLocation LocEnd = OMD->getCompoundBody(*Context)->getLocStart();
+
const char *startBuf = SM->getCharacterData(LocStart);
const char *endBuf = SM->getCharacterData(LocEnd);
ReplaceText(LocStart, endBuf-startBuf,
@@ -996,7 +996,7 @@
ObjCMethodDecl *OMD = *I;
RewriteObjCMethodDecl(OMD, ResultStr);
SourceLocation LocStart = OMD->getLocStart();
- SourceLocation LocEnd = OMD->getBody(*Context)->getLocStart();
+ SourceLocation LocEnd = OMD->getCompoundBody(*Context)->getLocStart();
const char *startBuf = SM->getCharacterData(LocStart);
const char *endBuf = SM->getCharacterData(LocEnd);
@@ -1426,6 +1426,7 @@
buf += "}\n";
// Insert all these *after* the statement body.
+ // FIXME: If this should support Obj-C++, support CXXTryStmt
if (isa<CompoundStmt>(S->getBody())) {
SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(1);
InsertText(endBodyLoc, buf.c_str(), buf.size());
@@ -4489,7 +4490,8 @@
// definitions using the same code.
RewriteBlocksInFunctionProtoType(FD->getType(), FD);
- if (CompoundStmt *Body = FD->getBody(*Context)) {
+ // FIXME: If this should support Obj-C++, support CXXTryStmt
+ if (CompoundStmt *Body = FD->getCompoundBody(*Context)) {
CurFunctionDef = FD;
CollectPropertySetters(Body);
CurrentBody = Body;
More information about the cfe-commits
mailing list