summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-11-28 22:33:28 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-11-28 22:33:28 +0000
commit8606d75265e4f162bcd81f08a5b59eec6ccc0ac6 (patch)
treef6b612698392e78146e05ce319b2a60262ba091e
parent836a93bdb3bbf6b2b63a72c04ae307b7ed4e578a (diff)
downloadbcm5719-llvm-8606d75265e4f162bcd81f08a5b59eec6ccc0ac6.tar.gz
bcm5719-llvm-8606d75265e4f162bcd81f08a5b59eec6ccc0ac6.zip
PR14388: An array or function type in an exception specification should be
decayed to a pointer type. Patch by WenHan Gu, with a little tweaking and additional testcases by me. llvm-svn: 168822
-rw-r--r--clang/include/clang/Sema/Sema.h2
-rw-r--r--clang/lib/Sema/SemaExceptionSpec.cpp35
-rw-r--r--clang/test/CodeGenCXX/exception-spec-decay.cpp33
-rw-r--r--clang/test/SemaCXX/exceptions.cpp23
4 files changed, 80 insertions, 13 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ee365c3299d..1e6ac187dc6 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -939,7 +939,7 @@ public:
CanThrowResult canThrow(const Expr *E);
const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc,
const FunctionProtoType *FPT);
- bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
+ bool CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
bool CheckEquivalentExceptionSpec(
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index e1f4888d632..8cb2cb4290e 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -38,8 +38,10 @@ static const FunctionProtoType *GetUnderlyingFunction(QualType T)
/// CheckSpecifiedExceptionType - Check if the given type is valid in an
/// exception specification. Incomplete types, or pointers to incomplete types
/// other than void are not allowed.
-bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
-
+///
+/// \param[in,out] T The exception type. This will be decayed to a pointer type
+/// when the input is an array or a function type.
+bool Sema::CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range) {
// This check (and the similar one below) deals with issue 437, that changes
// C++ 9.2p2 this way:
// Within the class member-specification, the class is regarded as complete
@@ -47,33 +49,42 @@ bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
// constructor ctor-initializers (including such things in nested classes).
if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
return false;
-
+
+ // C++ 15.4p2: A type cv T, "array of T", or "function returning T" denoted
+ // in an exception-specification is adjusted to type T, "pointer to T", or
+ // "pointer to function returning T", respectively.
// C++ 15.4p2: A type denoted in an exception-specification shall not denote
// an incomplete type.
- if (RequireCompleteType(Range.getBegin(), T,
- diag::err_incomplete_in_exception_spec,
- /*direct*/0, Range))
+ if (T->isArrayType())
+ T = Context.getArrayDecayedType(T);
+ else if (T->isFunctionType())
+ T = Context.getPointerType(T);
+ else if (RequireCompleteType(Range.getBegin(), T,
+ diag::err_incomplete_in_exception_spec,
+ /*direct*/0, Range))
return true;
+
// C++ 15.4p2: A type denoted in an exception-specification shall not denote
// an incomplete type a pointer or reference to an incomplete type, other
// than (cv) void*.
int kind;
+ QualType PointeeT = T;
if (const PointerType* IT = T->getAs<PointerType>()) {
- T = IT->getPointeeType();
+ PointeeT = IT->getPointeeType();
kind = 1;
} else if (const ReferenceType* IT = T->getAs<ReferenceType>()) {
- T = IT->getPointeeType();
+ PointeeT = IT->getPointeeType();
kind = 2;
} else
return false;
// Again as before
- if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
+ if (PointeeT->isRecordType() && PointeeT->getAs<RecordType>()->isBeingDefined())
return false;
-
- if (!T->isVoidType() &&
- RequireCompleteType(Range.getBegin(), T,
+
+ if (!PointeeT->isVoidType() &&
+ RequireCompleteType(Range.getBegin(), PointeeT,
diag::err_incomplete_in_exception_spec, kind, Range))
return true;
diff --git a/clang/test/CodeGenCXX/exception-spec-decay.cpp b/clang/test/CodeGenCXX/exception-spec-decay.cpp
new file mode 100644
index 00000000000..49283539070
--- /dev/null
+++ b/clang/test/CodeGenCXX/exception-spec-decay.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions %s -triple=i686-unknown-linux -emit-llvm -o - | FileCheck %s
+typedef int Array[10];
+
+void foo() throw (Array) {
+ throw 0;
+ // CHECK: landingpad
+ // CHECK-NEXT: filter {{.*}} @_ZTIPi
+}
+
+struct S {
+ void foo() throw (S[10]) {
+ throw 0;
+ }
+};
+
+template <typename T>
+struct S2 {
+ void foo() throw (T) {
+ throw 0;
+ }
+};
+
+int main() {
+ S s;
+ s.foo();
+ // CHECK: landingpad
+ // CHECK-NEXT: filter {{.*}} @_ZTIP1S
+
+ S2 <int[10]> s2;
+ s2.foo();
+ // CHECK: landingpad
+ // CHECK-NEXT: filter {{.*}} @_ZTIPi
+}
diff --git a/clang/test/SemaCXX/exceptions.cpp b/clang/test/SemaCXX/exceptions.cpp
index 486d88eab7b..8e32494825e 100644
--- a/clang/test/SemaCXX/exceptions.cpp
+++ b/clang/test/SemaCXX/exceptions.cpp
@@ -120,3 +120,26 @@ namespace PR6831 {
}
}
}
+
+namespace Decay {
+ struct A {
+ void f() throw (A[10]);
+ };
+
+ template<typename T> struct B {
+ void f() throw (B[10]);
+ };
+ template struct B<int>;
+
+ void f() throw (int[10], int(*)());
+ void f() throw (int*, int());
+
+ template<typename T> struct C {
+ void f() throw (T); // expected-error {{pointer to incomplete type 'Decay::E' is not allowed in exception specification}}
+ };
+ struct D {
+ C<D[10]> c;
+ };
+ struct E; // expected-note {{forward declaration}}
+ C<E[10]> e; // expected-note {{in instantiation of}}
+}
OpenPOWER on IntegriCloud