Skip to content

Commit 3c6f91e

Browse files
authored
[clang][dataflow] Fix result object location for builtin <=>. (#88726)
The newly added test causes an assertion failure in `PropagateResultObject()` without the fix added here.
1 parent e2c9109 commit 3c6f91e

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,11 @@ class ResultObjectVisitor : public RecursiveASTVisitor<ResultObjectVisitor> {
508508
isa<CXXStdInitializerListExpr>(E)) {
509509
return;
510510
}
511+
if (auto *Op = dyn_cast<BinaryOperator>(E);
512+
Op && Op->getOpcode() == BO_Cmp) {
513+
// Builtin `<=>` returns a `std::strong_ordering` object.
514+
return;
515+
}
511516

512517
if (auto *InitList = dyn_cast<InitListExpr>(E)) {
513518
if (!InitList->isSemanticForm())

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3098,6 +3098,58 @@ TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
30983098
});
30993099
}
31003100

3101+
// Check that the `std::strong_ordering` object returned by builtin `<=>` has a
3102+
// correctly modeled result object location.
3103+
TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) {
3104+
std::string Code = R"(
3105+
namespace std {
3106+
// This is the minimal definition required to get
3107+
// `Sema::CheckComparisonCategoryType()` to accept this fake.
3108+
struct strong_ordering {
3109+
enum class ordering { less, equal, greater };
3110+
ordering o;
3111+
static const strong_ordering less;
3112+
static const strong_ordering equivalent;
3113+
static const strong_ordering equal;
3114+
static const strong_ordering greater;
3115+
};
3116+
3117+
inline constexpr strong_ordering strong_ordering::less =
3118+
{ strong_ordering::ordering::less };
3119+
inline constexpr strong_ordering strong_ordering::equal =
3120+
{ strong_ordering::ordering::equal };
3121+
inline constexpr strong_ordering strong_ordering::equivalent =
3122+
{ strong_ordering::ordering::equal };
3123+
inline constexpr strong_ordering strong_ordering::greater =
3124+
{ strong_ordering::ordering::greater };
3125+
}
3126+
void target(int i, int j) {
3127+
auto ordering = i <=> j;
3128+
// [[p]]
3129+
}
3130+
)";
3131+
using ast_matchers::binaryOperator;
3132+
using ast_matchers::hasOperatorName;
3133+
using ast_matchers::match;
3134+
using ast_matchers::selectFirst;
3135+
using ast_matchers::traverse;
3136+
runDataflow(
3137+
Code,
3138+
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3139+
ASTContext &ASTCtx) {
3140+
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3141+
3142+
auto *Spaceship = selectFirst<BinaryOperator>(
3143+
"op",
3144+
match(binaryOperator(hasOperatorName("<=>")).bind("op"), ASTCtx));
3145+
3146+
EXPECT_EQ(
3147+
&Env.getResultObjectLocation(*Spaceship),
3148+
&getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "ordering"));
3149+
},
3150+
LangStandard::lang_cxx20);
3151+
}
3152+
31013153
TEST(TransferTest, ResultObjectLocationForStdInitializerListExpr) {
31023154
std::string Code = R"(
31033155
namespace std {

0 commit comments

Comments
 (0)