[cfe-commits] r83764 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/CMakeLists.txt lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExceptionSpec.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaType.cpp test/SemaCXX/exception-spec.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Sun Oct 11 02:03:14 PDT 2009
Author: cornedbee
Date: Sun Oct 11 04:03:14 2009
New Revision: 83764
URL: http://llvm.org/viewvc/llvm-project?rev=83764&view=rev
Log:
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.
Added:
cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (with props)
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/CMakeLists.txt
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/SemaCXX/exception-spec.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=83764&r1=83763&r2=83764&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Oct 11 04:03:14 2009
@@ -365,6 +365,10 @@
"base version">;
def err_incompatible_exception_specs : Error<
"target exception specification is not superset of source">;
+def err_return_type_specs_differ : Error<
+ "exception specifications of return types differ">;
+def err_arg_type_specs_differ : Error<
+ "exception specifications of argument types differ">;
// C++ access checking
def err_class_redeclared_with_different_access : Error<
Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=83764&r1=83763&r2=83764&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Sun Oct 11 04:03:14 2009
@@ -16,6 +16,7 @@
SemaDeclAttr.cpp
SemaDeclCXX.cpp
SemaDeclObjC.cpp
+ SemaExceptionSpec.cpp
SemaExpr.cpp
SemaExprCXX.cpp
SemaExprObjC.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=83764&r1=83763&r2=83764&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Oct 11 04:03:14 2009
@@ -482,9 +482,15 @@
bool CheckEquivalentExceptionSpec(
const FunctionProtoType *Old, SourceLocation OldLoc,
const FunctionProtoType *New, SourceLocation NewLoc);
+ bool CheckEquivalentExceptionSpec(unsigned DiagID, unsigned NoteID,
+ const FunctionProtoType *Old, SourceLocation OldLoc,
+ const FunctionProtoType *New, SourceLocation NewLoc);
bool CheckExceptionSpecSubset(unsigned DiagID, unsigned NoteID,
const FunctionProtoType *Superset, SourceLocation SuperLoc,
const FunctionProtoType *Subset, SourceLocation SubLoc);
+ bool CheckParamExceptionSpec(unsigned NoteID,
+ const FunctionProtoType *Target, SourceLocation TargetLoc,
+ const FunctionProtoType *Source, SourceLocation SourceLoc);
QualType ObjCGetTypeForMethodDefinition(DeclPtrTy D);
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=83764&r1=83763&r2=83764&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Oct 11 04:03:14 2009
@@ -4629,16 +4629,6 @@
return false;
}
-bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
- const CXXMethodDecl *Old) {
- return CheckExceptionSpecSubset(diag::err_override_exception_spec,
- diag::note_overridden_virtual_function,
- Old->getType()->getAs<FunctionProtoType>(),
- Old->getLocation(),
- New->getType()->getAs<FunctionProtoType>(),
- New->getLocation());
-}
-
/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
/// initializer for the declaration 'Dcl'.
/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
Added: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=83764&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (added)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Sun Oct 11 04:03:14 2009
@@ -0,0 +1,309 @@
+//===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ exception specification testing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace clang {
+
+static const FunctionProtoType *GetUnderlyingFunction(QualType T)
+{
+ if (const PointerType *PtrTy = T->getAs<PointerType>())
+ T = PtrTy->getPointeeType();
+ else if (const ReferenceType *RefTy = T->getAs<ReferenceType>())
+ T = RefTy->getPointeeType();
+ return T->getAs<FunctionProtoType>();
+}
+
+/// 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. But
+ // perhaps RequireCompleteType itself should contain this logic?
+
+ // C++ 15.4p2: A type denoted in an exception-specification shall not denote
+ // an incomplete type.
+ // FIXME: This isn't right. This will supress diagnostics from template
+ // instantiation and then simply emit the invalid type diagnostic.
+ if (RequireCompleteType(Range.getBegin(), T, 0))
+ 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->isVoidType() && RequireCompleteType(Range.getBegin(), T, 0))
+ 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) {
+ return CheckEquivalentExceptionSpec(diag::err_mismatched_exception_spec,
+ diag::note_previous_declaration,
+ Old, OldLoc, New, NewLoc);
+}
+
+/// 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(
+ unsigned DiagID, unsigned NoteID,
+ 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, DiagID);
+ if (NoteID != 0)
+ Diag(OldLoc, NoteID);
+ 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, DiagID);
+ if (NoteID != 0)
+ Diag(OldLoc, NoteID);
+ 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 CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+
+ // 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 half the gauntlet.
+ return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+}
+
+static bool CheckSpecForTypesEquivalent(Sema &S,
+ unsigned DiagID, unsigned NoteID,
+ QualType Target, SourceLocation TargetLoc,
+ QualType Source, SourceLocation SourceLoc)
+{
+ const FunctionProtoType *TFunc = GetUnderlyingFunction(Target);
+ if (!TFunc)
+ return false;
+ const FunctionProtoType *SFunc = GetUnderlyingFunction(Source);
+ if (!SFunc)
+ return false;
+
+ return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc,
+ SFunc, SourceLoc);
+}
+
+/// CheckParamExceptionSpec - Check if the parameter and return types of the
+/// two functions have equivalent exception specs. This is part of the
+/// assignment and override compatibility check. We do not check the parameters
+/// of parameter function pointers recursively, as no sane programmer would
+/// even be able to write such a function type.
+bool Sema::CheckParamExceptionSpec(unsigned NoteID,
+ const FunctionProtoType *Target, SourceLocation TargetLoc,
+ const FunctionProtoType *Source, SourceLocation SourceLoc)
+{
+ if (CheckSpecForTypesEquivalent(*this, diag::err_return_type_specs_differ, 0,
+ Target->getResultType(), TargetLoc,
+ Source->getResultType(), SourceLoc))
+ return true;
+
+ // We shouldn't even testing this unless the arguments are otherwise
+ // compatible.
+ assert(Target->getNumArgs() == Source->getNumArgs() &&
+ "Functions have different argument counts.");
+ for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) {
+ if (CheckSpecForTypesEquivalent(*this, diag::err_arg_type_specs_differ, 0,
+ Target->getArgType(i), TargetLoc,
+ Source->getArgType(i), SourceLoc))
+ return true;
+ }
+ return false;
+}
+
+bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
+{
+ // First we check for applicability.
+ // Target type must be a function, function pointer or function reference.
+ const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);
+ if (!ToFunc)
+ return false;
+
+ // SourceType must be a function or function pointer.
+ const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());
+ if (!FromFunc)
+ return false;
+
+ // Now we've got the correct types on both sides, check their compatibility.
+ // This means that the source of the conversion can only throw a subset of
+ // the exceptions of the target, and any exception specs on arguments or
+ // return types must be equivalent.
+ return CheckExceptionSpecSubset(diag::err_incompatible_exception_specs,
+ 0, ToFunc, From->getSourceRange().getBegin(),
+ FromFunc, SourceLocation());
+}
+
+bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old) {
+ return CheckExceptionSpecSubset(diag::err_override_exception_spec,
+ diag::note_overridden_virtual_function,
+ Old->getType()->getAs<FunctionProtoType>(),
+ Old->getLocation(),
+ New->getType()->getAs<FunctionProtoType>(),
+ New->getLocation());
+}
+
+} // end namespace clang
Propchange: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=83764&r1=83763&r2=83764&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Oct 11 04:03:14 2009
@@ -1275,38 +1275,6 @@
return false;
}
-bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
-{
- // First we check for applicability.
- // Target type must be a function, function pointer or function reference.
- if (const PointerType *PtrTy = ToType->getAs<PointerType>())
- ToType = PtrTy->getPointeeType();
- else if (const ReferenceType *RefTy = ToType->getAs<ReferenceType>())
- ToType = RefTy->getPointeeType();
-
- const FunctionProtoType *ToFunc = ToType->getAs<FunctionProtoType>();
- if (!ToFunc)
- return false;
-
- // SourceType must be a function or function pointer.
- // References are treated as functions.
- QualType FromType = From->getType();
- if (const PointerType *PtrTy = FromType->getAs<PointerType>())
- FromType = PtrTy->getPointeeType();
-
- const FunctionProtoType *FromFunc = FromType->getAs<FunctionProtoType>();
- if (!FromFunc)
- return false;
-
- // Now we've got the correct types on both sides, check their compatibility.
- // This means that the source of the conversion can only throw a subset of
- // the exceptions of the target, and any exception specs on arguments or
- // return types must be equivalent.
- return CheckExceptionSpecSubset(diag::err_incompatible_exception_specs,
- 0, ToFunc, From->getSourceRange().getBegin(),
- FromFunc, SourceLocation());
-}
-
Sema::OwningExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
SourceLocation KWLoc,
SourceLocation LParen,
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=83764&r1=83763&r2=83764&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sun Oct 11 04:03:14 2009
@@ -1413,190 +1413,6 @@
" 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) {
Modified: cfe/trunk/test/SemaCXX/exception-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/exception-spec.cpp?rev=83764&r1=83763&r2=83764&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/exception-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/exception-spec.cpp Sun Oct 11 04:03:14 2009
@@ -156,9 +156,9 @@
// return types and arguments must match exactly, no inheritance allowed
void (*(*t7)())() throw(B1) = &s8; // valid
- void (*(*t8)())() throw(A) = &s8; // invalid
- void (*(*t9)())() throw(D) = &s8; // invalid
+ void (*(*t8)())() throw(A) = &s8; // expected-error {{return types differ}} expected-error {{incompatible type}}
+ void (*(*t9)())() throw(D) = &s8; // expected-error {{return types differ}} expected-error {{incompatible type}}
void (*t10)(void (*)() throw(B1)) = &s9; // valid expected-warning{{disambiguated}}
- void (*t11)(void (*)() throw(A)) = &s9; // invalid expected-warning{{disambiguated}}
- void (*t12)(void (*)() throw(D)) = &s9; // invalid expected-warning{{disambiguated}}
+ void (*t11)(void (*)() throw(A)) = &s9; // expected-error {{argument types differ}} expected-error {{incompatible type}} expected-warning{{disambiguated}}
+ void (*t12)(void (*)() throw(D)) = &s9; // expected-error {{argument types differ}} expected-error {{incompatible type}} expected-warning{{disambiguated}}
}
More information about the cfe-commits
mailing list