From 9df8378b56bad3d3de049b55f3c0f0010bce4342 Mon Sep 17 00:00:00 2001 From: Andrey Ali Khan Bolshakov <32954549+bolshakov-a@users.noreply.github.com> Date: Tue, 30 Jan 2024 15:03:55 +0300 Subject: [PATCH] Fix analyzer crash on 'StructuralValue' (#79764) `OpaqueValueExpr` doesn't necessarily contain a source expression. Particularly, after #78041, it is used to carry the type and the value kind of a non-type template argument of floating-point type or referring to a subobject (those are so called `StructuralValue` arguments). This fixes #79575. (cherry picked from commit ef67f63fa5f950f4056b5783e92e137342805d74) --- clang/lib/Sema/SemaDecl.cpp | 3 ++- clang/lib/StaticAnalyzer/Core/Environment.cpp | 8 +++++--- clang/test/Analysis/templates.cpp | 13 +++++++++++++ .../SemaTemplate/temp_arg_nontype_cxx20.cpp | 17 +++++++++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f9bf1d14bdc4f6..a300badc6d0260 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12752,7 +12752,8 @@ namespace { } if (OpaqueValueExpr *OVE = dyn_cast(E)) { - HandleValue(OVE->getSourceExpr()); + if (Expr *SE = OVE->getSourceExpr()) + HandleValue(SE); return; } diff --git a/clang/lib/StaticAnalyzer/Core/Environment.cpp b/clang/lib/StaticAnalyzer/Core/Environment.cpp index 4f989ed59bee38..427f51109853bd 100644 --- a/clang/lib/StaticAnalyzer/Core/Environment.cpp +++ b/clang/lib/StaticAnalyzer/Core/Environment.cpp @@ -40,8 +40,11 @@ static const Expr *ignoreTransparentExprs(const Expr *E) { switch (E->getStmtClass()) { case Stmt::OpaqueValueExprClass: - E = cast(E)->getSourceExpr(); - break; + if (const Expr *SE = cast(E)->getSourceExpr()) { + E = SE; + break; + } + return E; case Stmt::ExprWithCleanupsClass: E = cast(E)->getSubExpr(); break; @@ -98,7 +101,6 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry, case Stmt::CXXBindTemporaryExprClass: case Stmt::ExprWithCleanupsClass: case Stmt::GenericSelectionExprClass: - case Stmt::OpaqueValueExprClass: case Stmt::ConstantExprClass: case Stmt::ParenExprClass: case Stmt::SubstNonTypeTemplateParmExprClass: diff --git a/clang/test/Analysis/templates.cpp b/clang/test/Analysis/templates.cpp index 061c19fe7e0445..6da1821b70f26f 100644 --- a/clang/test/Analysis/templates.cpp +++ b/clang/test/Analysis/templates.cpp @@ -68,3 +68,16 @@ namespace rdar13954714 { // force instantiation template void blockWithStatic(); } + +namespace structural_value_crash { + constexpr char abc[] = "abc"; + + template + void use_template_param() { + const char *p = in; + } + + void force_instantiate() { + use_template_param(); + } +} diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp index 834174cdf6a32d..ad73daa8e214c3 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp @@ -354,3 +354,20 @@ namespace ReportedRegression1 { return dummy.exit_code(); } } + +namespace ReportedRegression2 { + const char str[] = "dummy"; + + struct S { + S operator+(const char*) const; + }; + + template + void fn() { + auto s = S{} + in; + } + + void use() { + fn(); + } +}