diff --git a/clang_delta/CMakeLists.txt b/clang_delta/CMakeLists.txt index ab1dc420..c7ab58a5 100644 --- a/clang_delta/CMakeLists.txt +++ b/clang_delta/CMakeLists.txt @@ -158,6 +158,8 @@ add_executable(clang_delta RemovePointer.h RemoveTrivialBaseTemplate.cpp RemoveTrivialBaseTemplate.h + RemoveTryCatch.cpp + RemoveTryCatch.h RemoveUnresolvedBase.cpp RemoveUnresolvedBase.h RemoveUnusedEnumMember.cpp diff --git a/clang_delta/RemoveTryCatch.cpp b/clang_delta/RemoveTryCatch.cpp new file mode 100644 index 00000000..28cf3681 --- /dev/null +++ b/clang_delta/RemoveTryCatch.cpp @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2012, 2013, 2015 The University of Utah +// Copyright (c) 2012 Konstantin Tokarev +// All rights reserved. +// +// This file is distributed under the University of Illinois Open Source +// License. See the file COPYING for details. +// +//===----------------------------------------------------------------------===// + +#if HAVE_CONFIG_H +# include +#endif + +#include "RemoveTryCatch.h" + +#include +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/ASTContext.h" +#include "clang/Basic/SourceManager.h" + +#include "TransformationManager.h" + +using namespace clang; + +static const char *DescriptionMsg = +"Remove catch blocks and if not present the try block as well. \n"; + +static RegisterTransformation + Trans("remove-try-catch", DescriptionMsg); + +class RemoveTryCatchAnalysisVisitor : public + RecursiveASTVisitor { +public: + + explicit RemoveTryCatchAnalysisVisitor(RemoveTryCatch *Instance) + : ConsumerInstance(Instance) + { } + + bool VisitCXXTryStmt(CXXTryStmt *CTS); + +private: + + RemoveTryCatch *ConsumerInstance; +}; + +bool RemoveTryCatchAnalysisVisitor::VisitCXXTryStmt( + CXXTryStmt *CTS) +{ + if (ConsumerInstance->isInIncludedFile(CTS)) { + return true; + } + + // Count try block + ++ConsumerInstance->ValidInstanceNum; + + if (ConsumerInstance->TransformationCounter == + ConsumerInstance->ValidInstanceNum) { + ConsumerInstance->TheTryCatchStmt = CTS; + } + + int TmpInstanceNum = ConsumerInstance->ValidInstanceNum; + + // Count all catch blocks + ConsumerInstance->ValidInstanceNum += CTS->getNumHandlers(); + + // Early exit if the transformation counter is less than the index of any + // catch block + if (ConsumerInstance->TransformationCounter <= TmpInstanceNum) { + return true; + } + + // Early exit if the transformation counter is higher than the index of any + // catch block + if (ConsumerInstance->TransformationCounter > + ConsumerInstance->ValidInstanceNum) { + return true; + } + + TransAssert(ConsumerInstance->TransformationCounter > TmpInstanceNum); + + int CatchIdx = ConsumerInstance->TransformationCounter - TmpInstanceNum - 1; + ConsumerInstance->TheTryCatchStmt = CTS->getHandler(CatchIdx); + + // If the last catch block is removed the "try" has to be removed as well + if (CTS->getNumHandlers() == 1) { + ConsumerInstance->RewriteTryStmt = CTS; + } + + return true; +} + +void RemoveTryCatch::Initialize(ASTContext &context) +{ + Transformation::Initialize(context); + AnalysisVisitor = new RemoveTryCatchAnalysisVisitor(this); +} + +void RemoveTryCatch::HandleTranslationUnit(ASTContext &Ctx) +{ + AnalysisVisitor->TraverseDecl(Ctx.getTranslationUnitDecl()); + + if (QueryInstanceOnly) + return; + + if (TransformationCounter > ValidInstanceNum) { + TransError = TransMaxInstanceError; + return; + } + + Ctx.getDiagnostics().setSuppressAllDiagnostics(false); + + TransAssert(TheTryCatchStmt && "NULL TheTryCatchStmt!"); + + removeStmt(); + + if (Ctx.getDiagnostics().hasErrorOccurred() || + Ctx.getDiagnostics().hasFatalErrorOccurred()) + TransError = TransInternalError; +} + +void RemoveTryCatch::removeStmt() +{ + SourceRange Range = TheTryCatchStmt->getSourceRange(); + TheRewriter.RemoveText(Range); + + if (RewriteTryStmt != nullptr) { + TheRewriter.RemoveText(RewriteTryStmt->getLocStart(), 3); + } +} + +RemoveTryCatch::~RemoveTryCatch() +{ + delete AnalysisVisitor; +} diff --git a/clang_delta/RemoveTryCatch.h b/clang_delta/RemoveTryCatch.h new file mode 100644 index 00000000..ac85b3ba --- /dev/null +++ b/clang_delta/RemoveTryCatch.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2012 The University of Utah +// Copyright (c) 2012 Konstantin Tokarev +// All rights reserved. +// +// This file is distributed under the University of Illinois Open Source +// License. See the file COPYING for details. +// +//===----------------------------------------------------------------------===// + +#ifndef REMOVE_TRY_CATCH_H +#define REMOVE_TRY_CATCH_H + +#include +#include "llvm/ADT/DenseMap.h" +#include "Transformation.h" + +namespace clang { + class Stmt; +} + +class RemoveTryCatchAnalysisVisitor; + +class RemoveTryCatch : public Transformation { +friend class RemoveTryCatchAnalysisVisitor; + +public: + + RemoveTryCatch(const char *TransName, const char *Desc) + : Transformation(TransName, Desc), + AnalysisVisitor(0), + RewriteTryStmt(0), + TheTryCatchStmt(0) + { } + + ~RemoveTryCatch(); + +private: + + virtual void Initialize(clang::ASTContext &context); + + virtual void HandleTranslationUnit(clang::ASTContext &Ctx); + + void removeStmt(); + + RemoveTryCatchAnalysisVisitor *AnalysisVisitor; + + clang::Stmt *RewriteTryStmt; + clang::Stmt *TheTryCatchStmt; + + // Unimplemented + RemoveTryCatch(); + + RemoveTryCatch(const RemoveTryCatch &); + + void operator=(const RemoveTryCatch &); +}; +#endif diff --git a/creduce/creduce.in b/creduce/creduce.in index f7597ee8..4654661f 100644 --- a/creduce/creduce.in +++ b/creduce/creduce.in @@ -851,6 +851,7 @@ my @all_methods = ( { "name" => "pass_clang", "arg" => "replace-dependent-name", "pri" => 257, "C" => 1, }, { "name" => "pass_clang", "arg" => "simplify-recursive-template-instantiation", "pri" => 258, "C" => 1, }, { "name" => "pass_clang", "arg" => "vector-to-array", "pri" => 259, "C" => 1, }, + { "name" => "pass_clang", "arg" => "remove-try-catch", "pri" => 260, "C" => 1, }, { "name" => "pass_clang", "arg" => "combine-global-var", "last_pass_pri" => 990, "C" => 1, }, { "name" => "pass_clang", "arg" => "combine-local-var", "last_pass_pri" => 991, "C" => 1, }, { "name" => "pass_clang", "arg" => "simplify-struct-union-decl", "last_pass_pri" => 992, "C" => 1, },