diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-07-07 20:29:57 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-07-07 20:29:57 +0000 |
commit | 23c7d061367dd2fc1631e867cffc3d6aae24e799 (patch) | |
tree | 34a9556052405bbe7016547f676ebd54f25e99d3 /lib/Sema/SemaType.cpp | |
parent | 3292d5ce510061ea50152f53b7ab462b622176f4 (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.cpp | 90 |
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) { |