aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2009-07-07 20:29:57 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2009-07-07 20:29:57 +0000
commit23c7d061367dd2fc1631e867cffc3d6aae24e799 (patch)
tree34a9556052405bbe7016547f676ebd54f25e99d3 /lib/Sema/SemaType.cpp
parent3292d5ce510061ea50152f53b7ab462b622176f4 (diff)
Implement checking of exception spec compatibility for overriding virtual functions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74943 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index da61e6eb9e..8dcf4e48f5 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInherit.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
@@ -1237,6 +1238,95 @@ bool Sema::CheckEquivalentExceptionSpec(
return true;
}
+/// CheckExceptionSpecSubset - Check whether the second function type's
+/// exception specification is a subset (or equivalent) of the first function
+/// type. This is used by override and pointer assignment checks.
+bool Sema::CheckExceptionSpecSubset(unsigned DiagID, unsigned NoteID,
+ const FunctionProtoType *Superset, SourceLocation SuperLoc,
+ const FunctionProtoType *Subset, SourceLocation SubLoc)
+{
+ // FIXME: As usual, we could be more specific in our error messages, but
+ // that better waits until we've got types with source locations.
+
+ // If superset contains everything, we're done.
+ if (!Superset->hasExceptionSpec() || Superset->hasAnyExceptionSpec())
+ return false;
+
+ // It does not. If the subset contains everything, we've failed.
+ if (!Subset->hasExceptionSpec() || Subset->hasAnyExceptionSpec()) {
+ Diag(SubLoc, DiagID);
+ Diag(SuperLoc, NoteID);
+ return true;
+ }
+
+ // Neither contains everything. Do a proper comparison.
+ for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(),
+ SubE = Subset->exception_end(); SubI != SubE; ++SubI) {
+ // Take one type from the subset.
+ QualType CanonicalSubT = Context.getCanonicalType(*SubI);
+ bool SubIsPointer = false;
+ if (const ReferenceType *RefTy = CanonicalSubT->getAsReferenceType())
+ CanonicalSubT = RefTy->getPointeeType();
+ if (const PointerType *PtrTy = CanonicalSubT->getAsPointerType()) {
+ CanonicalSubT = PtrTy->getPointeeType();
+ SubIsPointer = true;
+ }
+ bool SubIsClass = CanonicalSubT->isRecordType();
+ CanonicalSubT.setCVRQualifiers(0);
+
+ BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false,
+ /*DetectVirtual=*/false);
+
+ bool Contained = false;
+ // Make sure it's in the superset.
+ for (FunctionProtoType::exception_iterator SuperI =
+ Superset->exception_begin(), SuperE = Superset->exception_end();
+ SuperI != SuperE; ++SuperI) {
+ QualType CanonicalSuperT = Context.getCanonicalType(*SuperI);
+ // SubT must be SuperT or derived from it, or pointer or reference to
+ // such types.
+ if (const ReferenceType *RefTy = CanonicalSuperT->getAsReferenceType())
+ CanonicalSuperT = RefTy->getPointeeType();
+ if (SubIsPointer) {
+ if (const PointerType *PtrTy = CanonicalSuperT->getAsPointerType())
+ CanonicalSuperT = PtrTy->getPointeeType();
+ else {
+ continue;
+ }
+ }
+ CanonicalSuperT.setCVRQualifiers(0);
+ // If the types are the same, move on to the next type in the subset.
+ if (CanonicalSubT == CanonicalSuperT) {
+ Contained = true;
+ break;
+ }
+
+ // Otherwise we need to check the inheritance.
+ if (!SubIsClass || !CanonicalSuperT->isRecordType())
+ continue;
+
+ Paths.clear();
+ if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths))
+ continue;
+
+ if (Paths.isAmbiguous(CanonicalSuperT))
+ continue;
+
+ // FIXME: Check base access. Don't forget to enable path recording.
+
+ Contained = true;
+ break;
+ }
+ if (!Contained) {
+ Diag(SubLoc, DiagID);
+ Diag(SuperLoc, NoteID);
+ return true;
+ }
+ }
+ // We've run the gauntlet.
+ return false;
+}
+
/// ObjCGetTypeForMethodDefinition - Builds the type for a method definition
/// declarator
QualType Sema::ObjCGetTypeForMethodDefinition(DeclPtrTy D) {