Author: isuckatcs Date: 2022-06-17T19:50:10+02:00 New Revision: e77ac66b8c1cf4f09f931d37749ed258f122d708
URL: https://github.com/llvm/llvm-project/commit/e77ac66b8c1cf4f09f931d37749ed258f122d708 DIFF: https://github.com/llvm/llvm-project/commit/e77ac66b8c1cf4f09f931d37749ed258f122d708.diff LOG: [Static Analyzer] Structured binding to data members Introducing structured binding to data members. Differential Revision: https://reviews.llvm.org/D127643 Added: clang/test/Analysis/uninit-structured-binding-struct.cpp Modified: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index a0c7dda896ef2..6ba19d52488c7 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -2591,9 +2591,22 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, // operator&. return; } - if (isa<BindingDecl>(D)) { - // FIXME: proper support for bound declarations. - // For now, let's just prevent crashing. + if (const auto *BD = dyn_cast<BindingDecl>(D)) { + const auto *DD = cast<DecompositionDecl>(BD->getDecomposedDecl()); + + if (const auto *ME = dyn_cast<MemberExpr>(BD->getBinding())) { + const auto *Field = cast<FieldDecl>(ME->getMemberDecl()); + + SVal Base = state->getLValue(DD, LCtx); + if (DD->getType()->isReferenceType()) { + Base = state->getSVal(Base.getAsRegion()); + } + + SVal V = state->getLValue(Field, Base); + + Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V)); + } + return; } diff --git a/clang/test/Analysis/uninit-structured-binding-struct.cpp b/clang/test/Analysis/uninit-structured-binding-struct.cpp new file mode 100644 index 0000000000000..fec82c0d8589d --- /dev/null +++ b/clang/test/Analysis/uninit-structured-binding-struct.cpp @@ -0,0 +1,116 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s + +void clang_analyzer_eval(bool); + +struct s { + int a; + int b; +}; + +void a(void) { + s tst; + + auto [i, j] = tst; + + int x = i; // expected-warning{{Assigned value is garbage or undefined}} +} + +void b(void) { + s tst; + tst.a = 1; + + auto [i, j] = tst; + + clang_analyzer_eval(i == 1); // expected-warning{{TRUE}} + int y = j; // expected-warning{{Assigned value is garbage or undefined}} +} + +void c(void) { + s tst; + + auto &[i, j] = tst; + + int x = i; // expected-warning{{Assigned value is garbage or undefined}} +} + +void d(void) { + s tst; + tst.a = 1; + + auto &[i, j] = tst; + + clang_analyzer_eval(i == 1); // expected-warning{{TRUE}} + i = 2; + clang_analyzer_eval(tst.a == 2); // expected-warning{{TRUE}} + + int y = j; // expected-warning{{Assigned value is garbage or undefined}} +} + +void e(void) { + s tst; + tst.a = 1; + + auto &[i, j] = tst; + + clang_analyzer_eval(i == 1); // expected-warning{{TRUE}} + + tst.b = 2; + clang_analyzer_eval(j == 2); // expected-warning{{TRUE}} +} + +void f(void) { + s tst; + + auto &&[i, j] = tst; + + int x = i; // expected-warning{{Assigned value is garbage or undefined}} +} + +void g(void) { + s tst; + tst.a = 1; + + auto &&[i, j] = tst; + + clang_analyzer_eval(i == 1); // expected-warning{{TRUE}} + int y = j; // expected-warning{{Assigned value is garbage or undefined}} +} + +struct s2 { + int a = 1; + int b = 2; +}; + +struct s3 { + s x; + s2 y; +}; + +void h(void) { + s3 tst; + + clang_analyzer_eval(tst.y.a == 1); // expected-warning{{TRUE}} + + auto [i, j] = tst; + + // FIXME: These should be undefined, but we have to fix + // reading undefined from lazy compound values first. + clang_analyzer_eval(i.a); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(i.b); // expected-warning{{UNKNOWN}} + + clang_analyzer_eval(j.a == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(j.b == 2); // expected-warning{{TRUE}} +} + +void i(void) { + s3 tst; + + clang_analyzer_eval(tst.y.a == 1); // expected-warning{{TRUE}} + + auto &[i, j] = tst; + j.a = 3; + + clang_analyzer_eval(tst.y.a == 3); // expected-warning{{TRUE}} + clang_analyzer_eval(tst.y.b == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(j.b == 2); // expected-warning{{TRUE}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits