diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-10-11 09:03:14 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-10-11 09:03:14 +0000 |
commit | dced226e37f7c2c31c25d06c514f29b610fe2a54 (patch) | |
tree | 30aa2297994e532099f846cc528e47c6c5a4b829 /lib/Sema/SemaType.cpp | |
parent | 13d50177b13161b209579e1f30a5e3cc72f7e2bd (diff) |
Test exception spec compatibility on return type and parameters.
Along the way, use RequireCompleteType when testing exception spec types.
Separate all the ugly spec stuff into its own file.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83764 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r-- | lib/Sema/SemaType.cpp | 184 |
1 files changed, 0 insertions, 184 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 5c7bbd0441..b82e5ec9b1 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1413,190 +1413,6 @@ void LocInfoType::getAsStringInternal(std::string &Str, " GetTypeFromParser"); } -/// 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*. - int kind; - if (const PointerType* IT = T->getAs<PointerType>()) { - T = IT->getPointeeType(); - kind = 1; - } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) { - T = IT->getPointeeType(); - kind = 2; - } 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. -bool Sema::CheckDistantExceptionSpec(QualType T) { - if (const PointerType *PT = T->getAs<PointerType>()) - T = PT->getPointeeType(); - else if (const MemberPointerType *PT = T->getAs<MemberPointerType>()) - T = PT->getPointeeType(); - else - return false; - - const FunctionProtoType *FnT = T->getAs<FunctionProtoType>(); - if (!FnT) - return false; - - return FnT->hasExceptionSpec(); -} - -/// CheckEquivalentExceptionSpec - Check if the two types have equivalent -/// exception specifications. Exception specifications are equivalent if -/// they allow exactly the same set of exception types. It does not matter how -/// that is achieved. See C++ [except.spec]p2. -bool Sema::CheckEquivalentExceptionSpec( - const FunctionProtoType *Old, SourceLocation OldLoc, - const FunctionProtoType *New, SourceLocation NewLoc) { - bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec(); - bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec(); - if (OldAny && NewAny) - return false; - if (OldAny || NewAny) { - Diag(NewLoc, diag::err_mismatched_exception_spec); - Diag(OldLoc, diag::note_previous_declaration); - return true; - } - - bool Success = true; - // Both have a definite exception spec. Collect the first set, then compare - // to the second. - llvm::SmallPtrSet<const Type*, 8> Types; - for (FunctionProtoType::exception_iterator I = Old->exception_begin(), - E = Old->exception_end(); I != E; ++I) - Types.insert(Context.getCanonicalType(*I).getTypePtr()); - - for (FunctionProtoType::exception_iterator I = New->exception_begin(), - E = New->exception_end(); I != E && Success; ++I) - Success = Types.erase(Context.getCanonicalType(*I).getTypePtr()); - - Success = Success && Types.empty(); - - if (Success) { - return false; - } - Diag(NewLoc, diag::err_mismatched_exception_spec); - Diag(OldLoc, diag::note_previous_declaration); - 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 (!SubLoc.isValid()) - SubLoc = SuperLoc; - - // 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); - if (NoteID != 0) - 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->getAs<ReferenceType>()) - CanonicalSubT = RefTy->getPointeeType(); - if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) { - CanonicalSubT = PtrTy->getPointeeType(); - SubIsPointer = true; - } - bool SubIsClass = CanonicalSubT->isRecordType(); - CanonicalSubT = CanonicalSubT.getUnqualifiedType(); - - CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, - /*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->getAs<ReferenceType>()) - CanonicalSuperT = RefTy->getPointeeType(); - if (SubIsPointer) { - if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>()) - CanonicalSuperT = PtrTy->getPointeeType(); - else { - continue; - } - } - CanonicalSuperT = CanonicalSuperT.getUnqualifiedType(); - // 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; - - if (FindInaccessibleBase(CanonicalSubT, CanonicalSuperT, Paths, true)) - continue; - - Contained = true; - break; - } - if (!Contained) { - Diag(SubLoc, DiagID); - if (NoteID != 0) - 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) { |