diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 8b2f8ecc5027e8..839c04c65e39e7 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -683,11 +683,11 @@ class TransferVisitor : public ConstStmtVisitor { assert( // The types are same, or Field->getType().getCanonicalType().getUnqualifiedType() == - Init->getType().getCanonicalType() || + Init->getType().getCanonicalType().getUnqualifiedType() || // The field's type is T&, and initializer is T (Field->getType()->isReferenceType() && - Field->getType().getCanonicalType()->getPointeeType() == - Init->getType().getCanonicalType())); + Field->getType().getCanonicalType()->getPointeeType() == + Init->getType().getCanonicalType())); auto& Loc = Env.createObject(Field->getType(), Init); FieldLocs.insert({Field, &Loc}); } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index bd9b98178b5d4e..ade0d202ced2f3 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -3197,6 +3197,26 @@ TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) { }); } +TEST(TransferTest, AggregateInitializationFunctionPointer) { + // This is a repro for an assertion failure. + // nullptr takes on the type of a const function pointer, but its type was + // asserted to be equal to the *unqualified* type of Field, which no longer + // included the const. + std::string Code = R"( + struct S { + void (*const Field)(); + }; + + void target() { + S s{nullptr}; + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + TEST(TransferTest, AssignToUnionMember) { std::string Code = R"( union A {