diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -231,6 +231,15 @@ void VisitDeclRefExpr(const DeclRefExpr *S) { const ValueDecl *VD = S->getDecl(); assert(VD != nullptr); + + // `DeclRefExpr`s to fields and non-static methods aren't glvalues, and + // there's also no sensible `Value` we can assign to them, so skip them. + if (isa(VD)) + return; + if (auto *Method = dyn_cast(VD); + Method && !Method->isStatic()) + return; + auto *DeclLoc = Env.getStorageLocation(*VD); if (DeclLoc == nullptr) return; @@ -397,8 +406,7 @@ propagateValueOrStorageLocation(*SubExpr, *S, Env); break; } - case CK_NullToPointer: - case CK_NullToMemberPointer: { + case CK_NullToPointer: { auto &Loc = Env.createStorageLocation(S->getType()); Env.setStorageLocation(*S, Loc); @@ -407,6 +415,10 @@ Env.setValue(Loc, NullPointerVal); break; } + case CK_NullToMemberPointer: + // FIXME: Implement pointers to members. For now, don't associate a value + // with this expression. + break; case CK_FunctionToPointerDecay: case CK_BuiltinFnToFnPtr: { StorageLocation *PointeeLoc = @@ -440,14 +452,12 @@ break; } case UO_AddrOf: { - // Do not form a pointer to a reference. If `SubExpr` is assigned a - // `ReferenceValue` then form a value that points to the location of its - // pointee. - StorageLocation *PointeeLoc = Env.getStorageLocationStrict(*SubExpr); - if (PointeeLoc == nullptr) + // FIXME: Model pointers to members. + if (S->getType()->isMemberPointerType()) break; - Env.setValueStrict(*S, Env.create(*PointeeLoc)); + if (StorageLocation *PointeeLoc = Env.getStorageLocationStrict(*SubExpr)) + Env.setValueStrict(*S, Env.create(*PointeeLoc)); break; } case UO_LNot: { diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2530,10 +2530,56 @@ }); } +TEST(TransferTest, PointerToMemberVariable) { + std::string Code = R"( + struct S { + int i; + }; + void target() { + int S::*MemberPointer = &S::i; + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + const ValueDecl *MemberPointerDecl = + findValueDecl(ASTCtx, "MemberPointer"); + ASSERT_THAT(MemberPointerDecl, NotNull()); + ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull()); + }); +} + +TEST(TransferTest, PointerToMemberFunction) { + std::string Code = R"( + struct S { + void Method(); + }; + void target() { + void (S::*MemberPointer)() = &S::Method; + // [[p]] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + const ValueDecl *MemberPointerDecl = + findValueDecl(ASTCtx, "MemberPointer"); + ASSERT_THAT(MemberPointerDecl, NotNull()); + ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull()); + }); +} + TEST(TransferTest, NullToMemberPointerCast) { std::string Code = R"( struct Foo {}; - void target(Foo *Foo) { + void target() { int Foo::*MemberPointer = nullptr; // [[p]] } @@ -2548,12 +2594,7 @@ const ValueDecl *MemberPointerDecl = findValueDecl(ASTCtx, "MemberPointer"); ASSERT_THAT(MemberPointerDecl, NotNull()); - - const auto *MemberPointerVal = - cast(Env.getValue(*MemberPointerDecl)); - - const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc(); - EXPECT_THAT(Env.getValue(MemberLoc), IsNull()); + ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull()); }); }