[PATCH] D61424: [ASTImporter] Fix inequivalence of unresolved exception spec
This revision was automatically updated to reflect the committed changes. Closed by commit rL360261: [ASTImporter] Fix inequivalence of unresolved exception spec (authored by martong, committed by ). Herald added a project: LLVM. Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D61424?vs=198626=198665#toc Repository: rL LLVM CHANGES SINCE LAST ACTION https://reviews.llvm.org/D61424/new/ https://reviews.llvm.org/D61424 Files: cfe/trunk/lib/AST/ASTImporter.cpp cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp Index: cfe/trunk/lib/AST/ASTImporter.cpp === --- cfe/trunk/lib/AST/ASTImporter.cpp +++ cfe/trunk/lib/AST/ASTImporter.cpp @@ -3130,6 +3130,11 @@ auto *Recent = const_cast( 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. Index: cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp === --- cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp +++ cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp @@ -322,6 +322,36 @@ return true; } +/// Check the equivalence of exception specifications. +static bool IsEquivalentExceptionSpec(StructuralEquivalenceContext , + 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 , QualType T1, QualType T2) { @@ -536,24 +566,8 @@ cast(OrigT1.getDesugaredType(Context.FromCtx)); const auto *OrigProto2 = cast(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; Index: cfe/trunk/lib/AST/ASTImporter.cpp === --- cfe/trunk/lib/AST/ASTImporter.cpp +++ cfe/trunk/lib/AST/ASTImporter.cpp @@ -3130,6 +3130,11 @@ auto *Recent = const_cast( 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. Index: cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp === --- cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp +++ cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp @@ -322,6 +322,36 @@ return true; } +/// Check the equivalence of
[PATCH] D61424: [ASTImporter] Fix inequivalence of unresolved exception spec
martong updated this revision to Diff 198626. martong marked 2 inline comments as done. martong added a comment. - Improve and fix typo in comments Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D61424/new/ https://reviews.llvm.org/D61424 Files: clang/lib/AST/ASTImporter.cpp clang/lib/AST/ASTStructuralEquivalence.cpp Index: clang/lib/AST/ASTStructuralEquivalence.cpp === --- clang/lib/AST/ASTStructuralEquivalence.cpp +++ clang/lib/AST/ASTStructuralEquivalence.cpp @@ -322,6 +322,36 @@ return true; } +/// Check the equivalence of exception specifications. +static bool IsEquivalentExceptionSpec(StructuralEquivalenceContext , + 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 , QualType T1, QualType T2) { @@ -536,24 +566,8 @@ cast(OrigT1.getDesugaredType(Context.FromCtx)); const auto *OrigProto2 = cast(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; Index: clang/lib/AST/ASTImporter.cpp === --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -3101,6 +3101,11 @@ auto *Recent = const_cast( 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. Index: clang/lib/AST/ASTStructuralEquivalence.cpp === --- clang/lib/AST/ASTStructuralEquivalence.cpp +++ clang/lib/AST/ASTStructuralEquivalence.cpp @@ -322,6 +322,36 @@ return true; } +/// Check the equivalence of exception specifications. +static bool IsEquivalentExceptionSpec(StructuralEquivalenceContext , + 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(), +
[PATCH] D61424: [ASTImporter] Fix inequivalence of unresolved exception spec
a_sidorin accepted this revision. a_sidorin added a comment. This revision is now accepted and ready to land. Looks good! Comment at: clang/lib/AST/ASTImporter.cpp:3107 +// noexcept-unevaluated, while the newly imported function may have an +// evaluated noexcept. } This looks to be true - a call `adjustExceptionSpec()` on the imported decl and its redeclarations can be required. Thank you for noticing this! Comment at: clang/lib/AST/ASTStructuralEquivalence.cpp:325 +/// Check the eqeuivalence of exception specifications. +static bool IsEquivalentExceptionSpec(StructuralEquivalenceContext , equivalence Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D61424/new/ https://reviews.llvm.org/D61424 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D61424: [ASTImporter] Fix inequivalence of unresolved exception spec
martong created this revision. martong added reviewers: a_sidorin, shafik. Herald added subscribers: cfe-commits, gamesh411, Szelethus, dkrupp, rnkovacs. Herald added a reviewer: a.sidorin. Herald added a project: clang. 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.) Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D61424 Files: clang/lib/AST/ASTImporter.cpp clang/lib/AST/ASTStructuralEquivalence.cpp Index: clang/lib/AST/ASTStructuralEquivalence.cpp === --- clang/lib/AST/ASTStructuralEquivalence.cpp +++ clang/lib/AST/ASTStructuralEquivalence.cpp @@ -322,6 +322,36 @@ return true; } +/// Check the eqeuivalence of exception specifications. +static bool IsEquivalentExceptionSpec(StructuralEquivalenceContext , + 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 , QualType T1, QualType T2) { @@ -536,24 +566,8 @@ cast(OrigT1.getDesugaredType(Context.FromCtx)); const auto *OrigProto2 = cast(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; Index: clang/lib/AST/ASTImporter.cpp === --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -3101,6 +3101,10 @@ auto *Recent = const_cast( FoundByLookup->getMostRecentDecl()); ToFunction->setPreviousDecl(Recent); +// FIXME Should we 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. } // Import Ctor initializers. Index: clang/lib/AST/ASTStructuralEquivalence.cpp === --- clang/lib/AST/ASTStructuralEquivalence.cpp +++ clang/lib/AST/ASTStructuralEquivalence.cpp @@ -322,6 +322,36 @@ return true; } +/// Check the eqeuivalence of exception specifications. +static bool IsEquivalentExceptionSpec(StructuralEquivalenceContext , + 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