This is an archive of the discontinued LLVM Phabricator instance.

[ASTImporter][AST] Fix structural equivalency crash on dependent FieldDecl
ClosedPublic

Authored by martong on Oct 1 2020, 8:49 AM.

Diff Detail

Event Timeline

martong created this revision.Oct 1 2020, 8:49 AM
martong requested review of this revision.Oct 1 2020, 8:49 AM

The added test causes the below assertion in the baseline (w/o the fix):

ASTTests: ../../git/llvm-project/clang/lib/AST/ExprConstant.cpp:14543: llvm::APSInt clang::Expr::EvaluateKnownConstInt(const clang::ASTContext&, llvm::SmallVectorImpl<std::pair<clang::SourceLocation, clang::PartialDiagnostic> >*) const: Assertion `!isValueDependent() && "Expression evaluator can't be called on a dependent expression."' failed.
shafik added a comment.Oct 1 2020, 5:04 PM

So was the bug we were saying there were falsely equivalent or falsely not equivalent?

teemperor requested changes to this revision.Oct 2 2020, 12:47 AM

Shouldn't this compare the actual width expressions? In other words, this patch wouldn't pass the test below:

TEST_F(StructuralEquivalenceTemplateTest, DependentFieldDeclDifferentVal) {
  const char *Code1 = "template <class A, class B> class foo { int a : sizeof(A); };";
  const char *Code2 = "template <class A, class B> class foo { int a : sizeof(B); };";
  auto t = makeNamedDecls(Code1, Code2, Lang_CXX03);
  EXPECT_FALSE(testStructuralMatch(t));
}

I don't want to derail the simple crash fix here, but I'm tempted to say that we might as well just simplify all this to return IsStructurallyEquivalent(Context, Field1->getBitWidth(), Field2->getBitWidth());. The nice diagnostic could live behind behind a check that ensures that both widths are not value-dependent.

If you want to keep this simple because you want to backport it I would also be fine with the current patch (not crashing is clearly an improvement)

So was the bug we were saying there were falsely equivalent or falsely not equivalent?

I think the bug is the crash :)

This revision now requires changes to proceed.Oct 2 2020, 12:47 AM

So was the bug we were saying there were falsely equivalent or falsely not equivalent?

I think the bug is the crash :)

Yes. More specifically, the call of getBitWidthValue() caused a segfault with release builds and with assertions enabled it caused the mentioned assert on the given test code.

Shouldn't this compare the actual width expressions? In other words, this patch wouldn't pass the test below:

TEST_F(StructuralEquivalenceTemplateTest, DependentFieldDeclDifferentVal) {
  const char *Code1 = "template <class A, class B> class foo { int a : sizeof(A); };";
  const char *Code2 = "template <class A, class B> class foo { int a : sizeof(B); };";
  auto t = makeNamedDecls(Code1, Code2, Lang_CXX03);
  EXPECT_FALSE(testStructuralMatch(t));
}

Yes, absolutely, it should. I have updated the patch this way, thanks! However, I was struggling to pass the existing lit test (ASTMerge/struct/test.c). Finally, I decided to remove all the BitField diagnostic code because it was already flawed - we called getBitWidthValue unchecked.

Currently, we are totally inconsistent about the diagnostics. Either we should emit a diagnostic before all return false or we should not ever emit any diags. The diagnostics in their current form are misleading, because there could be many notes missing. I am not sure how much do you guys value these diags in LLDB, but in CTU we simply don't care about them. I'd rather remove these diags from the equivalency check code, because they are causing only confusion. (Or we should properly implement and test all aspects of the diags.)

martong updated this revision to Diff 295800.Oct 2 2020, 5:11 AM
  • Delegate to BitWidth Expr matching in case of BitFields

So was the bug we were saying there were falsely equivalent or falsely not equivalent?

I think the bug is the crash :)

Yes. More specifically, the call of getBitWidthValue() caused a segfault with release builds and with assertions enabled it caused the mentioned assert on the given test code.

Thank you! From the test it was not obvious what was the actual cause of the crash so evaluating the correctness was difficult.

teemperor accepted this revision.Oct 5 2020, 2:40 AM

LGTM, thanks!

This revision is now accepted and ready to land.Oct 5 2020, 2:40 AM

I am not sure how much do you guys value these diags in LLDB

I think we don't even display them most of the time (IIUC they go to the diagnostic engine which is not always hooked up for the ASTs in LLDB as only a few actually come from Clang).

This revision was landed with ongoing or failed builds.Oct 5 2020, 5:22 AM
This revision was automatically updated to reflect the committed changes.

Currently, we are totally inconsistent about the diagnostics. Either we should emit a diagnostic before all return false or we should not ever emit any diags. The diagnostics in their current form are misleading, because there could be many notes missing. I am not sure how much do you guys value these diags in LLDB, but in CTU we simply don't care about them. I'd rather remove these diags from the equivalency check code, because they are causing only confusion. (Or we should properly implement and test all aspects of the diags.)

LGTM, thanks!

Thanks for the review!