[cfe-commits] r77475 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaStmt.cpp test/SemaCXX/unreachable-catch-clauses.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Wed Jul 29 10:15:46 PDT 2009
Author: cornedbee
Date: Wed Jul 29 12:15:45 2009
New Revision: 77475
URL: http://llvm.org/viewvc/llvm-project?rev=77475&view=rev
Log:
Check for identical types in C++ catch expression. Patch by Erik Verbruggen.
Added:
cfe/trunk/test/SemaCXX/unreachable-catch-clauses.cpp (with props)
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaStmt.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=77475&r1=77474&r2=77475&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jul 29 12:15:45 2009
@@ -1491,6 +1491,9 @@
def err_bad_memptr_lhs : Error<
"left hand operand to %0 must be a %select{|pointer to }1class "
"compatible with the right hand operand, but is %2">;
+def warn_exception_caught_by_earlier_handler : Warning<
+ "exception of type %0 will be caught by earlier handler">;
+def note_previous_exception_handler : Note<"for type %0">;
def err_conditional_void_nonvoid : Error<
"%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=77475&r1=77474&r2=77475&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Jul 29 12:15:45 2009
@@ -19,6 +19,8 @@
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
using namespace clang;
Sema::OwningStmtResult Sema::ActOnExprStmt(FullExprArg expr) {
@@ -1243,6 +1245,38 @@
HandlerBlock.takeAs<Stmt>()));
}
+class TypeWithHandler {
+ QualType t;
+ CXXCatchStmt *stmt;
+public:
+ TypeWithHandler(const QualType &type, CXXCatchStmt *statement)
+ : t(type), stmt(statement) {}
+
+ bool operator<(const TypeWithHandler &y) const {
+ if (t.getTypePtr() < y.t.getTypePtr())
+ return true;
+ else if (t.getTypePtr() > y.t.getTypePtr())
+ return false;
+ else if (t.getCVRQualifiers() < y.t.getCVRQualifiers())
+ return true;
+ else if (t.getCVRQualifiers() < y.t.getCVRQualifiers())
+ return false;
+ else
+ return getTypeSpecStartLoc() < y.getTypeSpecStartLoc();
+ }
+
+ bool operator==(const TypeWithHandler& other) const {
+ return t.getTypePtr() == other.t.getTypePtr()
+ && t.getCVRQualifiers() == other.t.getCVRQualifiers();
+ }
+
+ QualType getQualType() const { return t; }
+ CXXCatchStmt *getCatchStmt() const { return stmt; }
+ SourceLocation getTypeSpecStartLoc() const {
+ return stmt->getExceptionDecl()->getTypeSpecStartLoc();
+ }
+};
+
/// ActOnCXXTryBlock - Takes a try compound-statement and a number of
/// handlers and creates a try statement from them.
Action::OwningStmtResult
@@ -1253,13 +1287,44 @@
"The parser shouldn't call this if there are no handlers.");
Stmt **Handlers = reinterpret_cast<Stmt**>(RawHandlers.get());
- for(unsigned i = 0; i < NumHandlers - 1; ++i) {
+ llvm::SmallVector<TypeWithHandler, 8> TypesWithHandlers;
+
+ for(unsigned i = 0; i < NumHandlers; ++i) {
CXXCatchStmt *Handler = llvm::cast<CXXCatchStmt>(Handlers[i]);
- if (!Handler->getExceptionDecl())
- return StmtError(Diag(Handler->getLocStart(), diag::err_early_catch_all));
+ if (!Handler->getExceptionDecl()) {
+ if (i < NumHandlers - 1)
+ return StmtError(Diag(Handler->getLocStart(),
+ diag::err_early_catch_all));
+
+ continue;
+ }
+
+ const QualType CaughtType = Handler->getCaughtType();
+ const QualType CanonicalCaughtType = Context.getCanonicalType(CaughtType);
+ TypesWithHandlers.push_back(TypeWithHandler(CanonicalCaughtType, Handler));
+ }
+
+ // Detect handlers for the same type as an earlier one.
+ if (NumHandlers > 1) {
+ llvm::array_pod_sort(TypesWithHandlers.begin(), TypesWithHandlers.end());
+
+ TypeWithHandler prev = TypesWithHandlers[0];
+ for (unsigned i = 1; i < TypesWithHandlers.size(); ++i) {
+ TypeWithHandler curr = TypesWithHandlers[i];
+
+ if (curr == prev) {
+ Diag(curr.getTypeSpecStartLoc(),
+ diag::warn_exception_caught_by_earlier_handler)
+ << curr.getCatchStmt()->getCaughtType().getAsString();
+ Diag(prev.getTypeSpecStartLoc(),
+ diag::note_previous_exception_handler)
+ << prev.getCatchStmt()->getCaughtType().getAsString();
+ }
+
+ prev = curr;
+ }
}
- // FIXME: We should detect handlers for the same type as an earlier one.
- // This one is rather easy.
+
// FIXME: We should detect handlers that cannot catch anything because an
// earlier handler catches a superclass. Need to find a method that is not
// quadratic for this.
Added: cfe/trunk/test/SemaCXX/unreachable-catch-clauses.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/unreachable-catch-clauses.cpp?rev=77475&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/unreachable-catch-clauses.cpp (added)
+++ cfe/trunk/test/SemaCXX/unreachable-catch-clauses.cpp Wed Jul 29 12:15:45 2009
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+class BaseEx {};
+class Ex1: public BaseEx {};
+typedef Ex1 Ex2;
+
+void f();
+
+void test()
+try {}
+catch (BaseEx &e) { f(); }
+catch (Ex1 &e) { f(); } // expected-note {{for type class Ex1 &}}
+catch (Ex2 &e) { f(); } // expected-warning {{exception of type Ex2 & will be caught by earlier handler}}
+
Propchange: cfe/trunk/test/SemaCXX/unreachable-catch-clauses.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/SemaCXX/unreachable-catch-clauses.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/SemaCXX/unreachable-catch-clauses.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list