aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2009-05-29 18:02:33 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2009-05-29 18:02:33 +0000
commitef65f06e8e440aec541442cfd73a8a836e9bc842 (patch)
treec62611a51513fbe058801939f3a6adc116fca546 /lib/Sema/SemaType.cpp
parent8ebefded18aa3c83b6b4ce3713060c94432f9859 (diff)
Reject incomplete types in exception specs.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72580 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp60
1 files changed, 53 insertions, 7 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 01b8aa4fd4..833620b5cf 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -760,13 +760,17 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
// function takes no arguments.
llvm::SmallVector<QualType, 4> Exceptions;
Exceptions.reserve(FTI.NumExceptions);
- for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei)
- Exceptions.push_back(
- QualType::getFromOpaquePtr(FTI.Exceptions[ei]));
+ for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
+ QualType ET = QualType::getFromOpaquePtr(FTI.Exceptions[ei].Ty);
+ // Check that the type is valid for an exception spec, and drop it
+ // if not.
+ if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range))
+ Exceptions.push_back(ET);
+ }
T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, FTI.TypeQuals,
FTI.hasExceptionSpec,
FTI.hasAnyExceptionSpec,
- FTI.NumExceptions, Exceptions.data());
+ Exceptions.size(), Exceptions.data());
} else if (FTI.isVariadic) {
// We allow a zero-parameter variadic function in C if the
// function is marked with the "overloadable"
@@ -843,14 +847,19 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
llvm::SmallVector<QualType, 4> Exceptions;
Exceptions.reserve(FTI.NumExceptions);
- for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei)
- Exceptions.push_back(QualType::getFromOpaquePtr(FTI.Exceptions[ei]));
+ for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
+ QualType ET = QualType::getFromOpaquePtr(FTI.Exceptions[ei].Ty);
+ // Check that the type is valid for an exception spec, and drop it if
+ // not.
+ if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range))
+ Exceptions.push_back(ET);
+ }
T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(),
FTI.isVariadic, FTI.TypeQuals,
FTI.hasExceptionSpec,
FTI.hasAnyExceptionSpec,
- FTI.NumExceptions, Exceptions.data());
+ Exceptions.size(), Exceptions.data());
}
break;
}
@@ -953,6 +962,43 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
return 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) {
+ // FIXME: This may not correctly work with the fix for core issue 437,
+ // where a class's own type is considered complete within its body.
+
+ // C++ 15.4p2: A type denoted in an exception-specification shall not denote
+ // an incomplete type.
+ if (T->isIncompleteType())
+ return Diag(Range.getBegin(), diag::err_incomplete_in_exception_spec)
+ << Range << T << /*direct*/0;
+
+ // 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*.
+ // The standard does not mention member pointers, but it has to mean them too.
+ int kind;
+ if (const PointerType* IT = T->getAsPointerType()) {
+ T = IT->getPointeeType();
+ kind = 1;
+ } else if (const MemberPointerType* IT = T->getAsMemberPointerType()) {
+ T = IT->getPointeeType();
+ kind = 2;
+ } else if (const ReferenceType* IT = T->getAsReferenceType()) {
+ T = IT->getPointeeType();
+ kind = 3;
+ } else
+ return false;
+
+ if (T->isIncompleteType() && !T->isVoidType())
+ return Diag(Range.getBegin(), diag::err_incomplete_in_exception_spec)
+ << Range << T << /*indirect*/kind;
+
+ return false;
+}
+
/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer
/// to member to a function with an exception specification. This means that
/// it is invalid to add another level of indirection.