Author: T-Gruber Date: 2024-10-25T11:59:16+02:00 New Revision: 86d65ae7949e0322f10e1856c5c33caa34ebfe2f
URL: https://github.com/llvm/llvm-project/commit/86d65ae7949e0322f10e1856c5c33caa34ebfe2f DIFF: https://github.com/llvm/llvm-project/commit/86d65ae7949e0322f10e1856c5c33caa34ebfe2f.diff LOG: [analyzer] Improve FieldRegion descriptive name (#112313) The current implementation of MemRegion::getDescriptiveName fails for FieldRegions whose SuperRegion is an ElementRegion. As outlined below: ```Cpp struct val_struct { int val; }; extern struct val_struct val_struct_array[3]; void func(){ // FieldRegion with ElementRegion as SuperRegion. val_struct_array[0].val; } ``` For this special case, the expression cannot be pretty printed and must therefore be obtained separately. Added: Modified: clang/lib/StaticAnalyzer/Core/MemRegion.cpp clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 0a29a050bbc2ba..02d1358a2001ef 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -722,6 +722,13 @@ std::string MemRegion::getDescriptiveName(bool UseQuotes) const { SmallString<50> buf; llvm::raw_svector_ostream os(buf); + // Enclose subject with single quotes if needed. + auto QuoteIfNeeded = [UseQuotes](const Twine &Subject) -> std::string { + if (UseQuotes) + return ("'" + Subject + "'").str(); + return Subject.str(); + }; + // Obtain array indices to add them to the variable name. const ElementRegion *ER = nullptr; while ((ER = R->getAs<ElementRegion>())) { @@ -751,12 +758,20 @@ std::string MemRegion::getDescriptiveName(bool UseQuotes) const { } // Get variable name. - if (R && R->canPrintPrettyAsExpr()) { - R->printPrettyAsExpr(os); - if (UseQuotes) - return (llvm::Twine("'") + os.str() + ArrayIndices + "'").str(); - else - return (llvm::Twine(os.str()) + ArrayIndices).str(); + if (R) { + // MemRegion can be pretty printed. + if (R->canPrintPrettyAsExpr()) { + R->printPrettyAsExpr(os); + return QuoteIfNeeded(llvm::Twine(os.str()) + ArrayIndices); + } + + // FieldRegion may have ElementRegion as SuperRegion. + if (const auto *FR = R->getAs<FieldRegion>()) { + std::string Super = FR->getSuperRegion()->getDescriptiveName(false); + if (Super.empty()) + return ""; + return QuoteIfNeeded(Super + "." + FR->getDecl()->getName()); + } } return VariableName; diff --git a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp index b13e7123ee524d..0f6e49bf42f4ac 100644 --- a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp +++ b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp @@ -12,7 +12,6 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "gtest/gtest.h" -#include <fstream> using namespace clang; using namespace ento; @@ -143,4 +142,32 @@ void top() { EXPECT_EQ(Output, "DescriptiveNameChecker: array[x]\n"); } +TEST(MemRegionDescriptiveNameTest, FieldRegWithSuperElementReg) { + StringRef Code = R"cpp( +void reportDescriptiveName(int *p); +struct val_struct { int val; }; +extern struct val_struct val_struct_array[3]; +void top() { + reportDescriptiveName(&val_struct_array[0].val); +})cpp"; + + std::string Output; + ASSERT_TRUE(runChecker(Code, Output)); + EXPECT_EQ(Output, "DescriptiveNameChecker: val_struct_array[0].val\n"); +} + +TEST(MemRegionDescriptiveNameTest, FieldRegWithSuperMultidimElementReg) { + StringRef Code = R"cpp( +void reportDescriptiveName(int *p); +struct val_struct { int val; }; +extern struct val_struct val_struct_array[3][4]; +void top() { + reportDescriptiveName(&val_struct_array[1][2].val); +})cpp"; + + std::string Output; + ASSERT_TRUE(runChecker(Code, Output)); + EXPECT_EQ(Output, "DescriptiveNameChecker: val_struct_array[1][2].val\n"); +} + } // namespace _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits