Make checkIdenticalDefaultArguments more precise

...by structurally comparing complex constexpr exprs that use template functions
that happen to not have been instantiated, so Expr::EvaluateAsRValue et al would
fail.  (Which happened with SFX_PRINTER_ALL in SfxViewShell::SetPrinter,
include/sfx2/viewsh.hxx.)

Now all of the LO code base should compile without causing
checkIdenticalDefaultArguments to return Maybe.

Change-Id: I2b103418c2c68f6d2242535c9cca3222a2508778
Reviewed-on: https://gerrit.libreoffice.org/44773
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
This commit is contained in:
Stephan Bergmann
2017-11-15 17:41:22 +01:00
parent fa7f2ec536
commit 4ff66e42bf
2 changed files with 97 additions and 0 deletions

View File

@@ -38,6 +38,76 @@ Expr const * skipImplicit(Expr const * expr) {
return expr;
}
bool structurallyIdentical(Stmt const * stmt1, Stmt const * stmt2) {
if (stmt1->getStmtClass() != stmt2->getStmtClass()) {
return false;
}
switch (stmt1->getStmtClass()) {
case Stmt::CXXConstructExprClass:
if (cast<CXXConstructExpr>(stmt1)->getConstructor()->getCanonicalDecl()
!= cast<CXXConstructExpr>(stmt2)->getConstructor()->getCanonicalDecl())
{
return false;
}
break;
case Stmt::DeclRefExprClass:
if (cast<DeclRefExpr>(stmt1)->getDecl()->getCanonicalDecl()
!= cast<DeclRefExpr>(stmt2)->getDecl()->getCanonicalDecl())
{
return false;
}
break;
case Stmt::ImplicitCastExprClass:
{
auto const e1 = cast<ImplicitCastExpr>(stmt1);
auto const e2 = cast<ImplicitCastExpr>(stmt2);
if (e1->getCastKind() != e2->getCastKind()
|| e1->getType().getCanonicalType() != e2->getType().getCanonicalType())
{
return false;
}
break;
}
case Stmt::MemberExprClass:
{
auto const e1 = cast<MemberExpr>(stmt1);
auto const e2 = cast<MemberExpr>(stmt2);
if (e1->isArrow() != e2->isArrow()
|| e1->getType().getCanonicalType() != e2->getType().getCanonicalType())
{
return false;
}
break;
}
case Stmt::CXXMemberCallExprClass:
case Stmt::CXXOperatorCallExprClass:
if (cast<Expr>(stmt1)->getType().getCanonicalType()
!= cast<Expr>(stmt2)->getType().getCanonicalType())
{
return false;
}
break;
case Stmt::MaterializeTemporaryExprClass:
case Stmt::ParenExprClass:
break;
default:
// Conservatively assume non-identical for expressions that don't happen for us in practice
// when compiling the LO code base (and for which the above set of supported classes would
// need to be extended):
return false;
}
auto i1 = stmt1->child_begin();
auto e1 = stmt1->child_end();
auto i2 = stmt2->child_begin();
auto e2 = stmt2->child_end();
for (; i1 != e1; ++i1, ++i2) {
if (i2 == e2 || !structurallyIdentical(*i1, *i2)) {
return false;
}
}
return i2 == e2;
}
}
Plugin::Plugin( const InstantiationData& data )
@@ -294,6 +364,12 @@ Plugin::IdenticalDefaultArgumentsResult Plugin::checkIdenticalDefaultArguments(
}
break;
}
// If the EvaluateAsRValue derivatives above failed because the arguments use e.g. (constexpr)
// function template specializations that happen to not have been instantiated in this TU, try a
// structural comparison of the arguments:
if (structurallyIdentical(argument1, argument2)) {
return IdenticalDefaultArgumentsResult::Yes;
}
return IdenticalDefaultArgumentsResult::Maybe;
}