forked from OSchip/llvm-project
[ASTImporter] Fix inequivalence of unresolved exception spec
Summary: Structural equivalence of methods can falsely report false when the exception specifier is unresolved (i.e unevaluated or not instantiated). (This caused one assertion during bitcoin ctu-analysis.) Reviewers: a_sidorin, shafik, a.sidorin Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D61424 llvm-svn: 360261
This commit is contained in:
parent
9fd02a71a3
commit
ce6b78128f
|
@ -3130,6 +3130,11 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
auto *Recent = const_cast<FunctionDecl *>(
|
||||
FoundByLookup->getMostRecentDecl());
|
||||
ToFunction->setPreviousDecl(Recent);
|
||||
// FIXME Probably we should merge exception specifications. E.g. In the
|
||||
// "To" context the existing function may have exception specification with
|
||||
// noexcept-unevaluated, while the newly imported function may have an
|
||||
// evaluated noexcept. A call to adjustExceptionSpec() on the imported
|
||||
// decl and its redeclarations may be required.
|
||||
}
|
||||
|
||||
// Import Ctor initializers.
|
||||
|
|
|
@ -322,6 +322,36 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Check the equivalence of exception specifications.
|
||||
static bool IsEquivalentExceptionSpec(StructuralEquivalenceContext &Context,
|
||||
const FunctionProtoType *Proto1,
|
||||
const FunctionProtoType *Proto2) {
|
||||
|
||||
auto Spec1 = Proto1->getExceptionSpecType();
|
||||
auto Spec2 = Proto2->getExceptionSpecType();
|
||||
|
||||
if (isUnresolvedExceptionSpec(Spec1) || isUnresolvedExceptionSpec(Spec2))
|
||||
return true;
|
||||
|
||||
if (Spec1 != Spec2)
|
||||
return false;
|
||||
if (Spec1 == EST_Dynamic) {
|
||||
if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
|
||||
return false;
|
||||
for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
|
||||
if (!IsStructurallyEquivalent(Context, Proto1->getExceptionType(I),
|
||||
Proto2->getExceptionType(I)))
|
||||
return false;
|
||||
}
|
||||
} else if (isComputedNoexcept(Spec1)) {
|
||||
if (!IsStructurallyEquivalent(Context, Proto1->getNoexceptExpr(),
|
||||
Proto2->getNoexceptExpr()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Determine structural equivalence of two types.
|
||||
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
QualType T1, QualType T2) {
|
||||
|
@ -536,24 +566,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||
cast<FunctionProtoType>(OrigT1.getDesugaredType(Context.FromCtx));
|
||||
const auto *OrigProto2 =
|
||||
cast<FunctionProtoType>(OrigT2.getDesugaredType(Context.ToCtx));
|
||||
auto Spec1 = OrigProto1->getExceptionSpecType();
|
||||
auto Spec2 = OrigProto2->getExceptionSpecType();
|
||||
|
||||
if (Spec1 != Spec2)
|
||||
if (!IsEquivalentExceptionSpec(Context, OrigProto1, OrigProto2))
|
||||
return false;
|
||||
if (Spec1 == EST_Dynamic) {
|
||||
if (OrigProto1->getNumExceptions() != OrigProto2->getNumExceptions())
|
||||
return false;
|
||||
for (unsigned I = 0, N = OrigProto1->getNumExceptions(); I != N; ++I) {
|
||||
if (!IsStructurallyEquivalent(Context, OrigProto1->getExceptionType(I),
|
||||
OrigProto2->getExceptionType(I)))
|
||||
return false;
|
||||
}
|
||||
} else if (isComputedNoexcept(Spec1)) {
|
||||
if (!IsStructurallyEquivalent(Context, OrigProto1->getNoexceptExpr(),
|
||||
OrigProto2->getNoexceptExpr()))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fall through to check the bits common with FunctionNoProtoType.
|
||||
LLVM_FALLTHROUGH;
|
||||
|
|
Loading…
Reference in New Issue