[clang] 2b1a517 - Revert "[clang][dataflow] Only model struct fields that are used in the function being analyzed."
Yitzhak Mandelbaum via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 5 17:08:03 PST 2023
Author: Yitzhak Mandelbaum
Date: 2023-01-06T01:07:28Z
New Revision: 2b1a517a92bfdfa3b692a660e19a2bb22513a567
URL: https://github.com/llvm/llvm-project/commit/2b1a517a92bfdfa3b692a660e19a2bb22513a567
DIFF: https://github.com/llvm/llvm-project/commit/2b1a517a92bfdfa3b692a660e19a2bb22513a567.diff
LOG: Revert "[clang][dataflow] Only model struct fields that are used in the function being analyzed."
This reverts commit 5e8f597c2fedc740b71f07dfdb1ef3c2d348b193. It caused msan and ubsan breakages.
Added:
Modified:
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/lib/Analysis/FlowSensitive/Transfer.cpp
clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
clang/unittests/Analysis/FlowSensitive/TestingSupport.h
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
index 98135508aabb..f8ee5864482b 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -54,21 +54,14 @@ llvm::DenseSet<const FieldDecl *> getObjectFields(QualType Type);
/// is used during dataflow analysis.
class DataflowAnalysisContext {
public:
- // FIXME: merge with TransferOptions from Transfer.h.
- struct Options {
- bool EnableContextSensitiveAnalysis;
- };
-
/// Constructs a dataflow analysis context.
///
/// Requirements:
///
/// `S` must not be null.
- DataflowAnalysisContext(std::unique_ptr<Solver> S,
- Options Opts = {
- /*EnableContextSensitiveAnalysis=*/false})
+ DataflowAnalysisContext(std::unique_ptr<Solver> S)
: S(std::move(S)), TrueVal(createAtomicBoolValue()),
- FalseVal(createAtomicBoolValue()), Options(Opts) {
+ FalseVal(createAtomicBoolValue()) {
assert(this->S != nullptr);
}
@@ -260,11 +253,7 @@ class DataflowAnalysisContext {
/// returns null.
const ControlFlowContext *getControlFlowContext(const FunctionDecl *F);
- void addFieldsReferencedInScope(llvm::DenseSet<const FieldDecl *> Fields);
-
private:
- friend class Environment;
-
struct NullableQualTypeDenseMapInfo : private llvm::DenseMapInfo<QualType> {
static QualType getEmptyKey() {
// Allow a NULL `QualType` by using a
diff erent value as the empty key.
@@ -276,10 +265,6 @@ class DataflowAnalysisContext {
using DenseMapInfo::isEqual;
};
- /// Returns the subset of fields of `Type` that are referenced in the scope of
- /// the analysis.
- llvm::DenseSet<const FieldDecl *> getReferencedFields(QualType Type);
-
/// Adds all constraints of the flow condition identified by `Token` and all
/// of its transitive dependencies to `Constraints`. `VisitedTokens` is used
/// to track tokens of flow conditions that were already visited by recursive
@@ -345,8 +330,6 @@ class DataflowAnalysisContext {
AtomicBoolValue &TrueVal;
AtomicBoolValue &FalseVal;
- Options Options;
-
// Indices that are used to avoid recreating the same composite boolean
// values.
llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ConjunctionValue *>
@@ -376,9 +359,6 @@ class DataflowAnalysisContext {
llvm::DenseMap<AtomicBoolValue *, BoolValue *> FlowConditionConstraints;
llvm::DenseMap<const FunctionDecl *, ControlFlowContext> FunctionContexts;
-
- // All fields referenced (statically) in the scope of the analysis.
- llvm::DenseSet<const FieldDecl *> FieldsReferencedInScope;
};
} // namespace dataflow
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index fbc5f6d2c889..c1653c2ab4ed 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -452,9 +452,6 @@ class Environment {
void pushCallInternal(const FunctionDecl *FuncDecl,
ArrayRef<const Expr *> Args);
- /// Assigns storage locations and values to all variables in `Vars`.
- void initVars(llvm::DenseSet<const VarDecl *> Vars);
-
// `DACtx` is not null and not owned by this object.
DataflowAnalysisContext *DACtx;
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index 6b7b2dc8912b..af2f1fcbe24e 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -16,7 +16,6 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Analysis/FlowSensitive/DebugSupport.h"
#include "clang/Analysis/FlowSensitive/Value.h"
-#include "llvm/ADT/SetOperations.h"
#include "llvm/Support/Debug.h"
#include <cassert>
#include <memory>
@@ -25,33 +24,13 @@
namespace clang {
namespace dataflow {
-void DataflowAnalysisContext::addFieldsReferencedInScope(
- llvm::DenseSet<const FieldDecl *> Fields) {
- llvm::set_union(FieldsReferencedInScope, Fields);
-}
-
-llvm::DenseSet<const FieldDecl *>
-DataflowAnalysisContext::getReferencedFields(QualType Type) {
- llvm::DenseSet<const FieldDecl *> Fields = getObjectFields(Type);
- llvm::set_intersect(Fields, FieldsReferencedInScope);
- return Fields;
-}
-
StorageLocation &DataflowAnalysisContext::createStorageLocation(QualType Type) {
if (!Type.isNull() &&
(Type->isStructureOrClassType() || Type->isUnionType())) {
+ // FIXME: Explore options to avoid eager initialization of fields as some of
+ // them might not be needed for a particular analysis.
llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
- // During context-sensitive analysis, a struct may be allocated in one
- // function, but its field accessed in a function lower in the stack than
- // the allocation. Since we only collect fields used in the function where
- // the allocation occurs, we can't apply that filter when performing
- // context-sensitive analysis. But, this only applies to storage locations,
- // since fields access it not allowed to fail. In contrast, field *values*
- // don't need this allowance, since the API allows for uninitialized fields.
- auto Fields = Options.EnableContextSensitiveAnalysis
- ? getObjectFields(Type)
- : getReferencedFields(Type);
- for (const FieldDecl *Field : Fields)
+ for (const FieldDecl *Field : getObjectFields(Type))
FieldLocs.insert({Field, &createStorageLocation(Field->getType())});
return takeOwnership(
std::make_unique<AggregateStorageLocation>(Type, std::move(FieldLocs)));
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 936f10ef3824..1a561b31aae9 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -151,62 +151,44 @@ static Value &widenDistinctValues(QualType Type, Value &Prev,
}
/// Initializes a global storage value.
-static void insertIfGlobal(const Decl &D,
- llvm::DenseSet<const FieldDecl *> &Fields,
- llvm::DenseSet<const VarDecl *> &Vars) {
+static void initGlobalVar(const VarDecl &D, Environment &Env) {
+ if (!D.hasGlobalStorage() ||
+ Env.getStorageLocation(D, SkipPast::None) != nullptr)
+ return;
+
+ auto &Loc = Env.createStorageLocation(D);
+ Env.setStorageLocation(D, Loc);
+ if (auto *Val = Env.createValue(D.getType()))
+ Env.setValue(Loc, *Val);
+}
+
+/// Initializes a global storage value.
+static void initGlobalVar(const Decl &D, Environment &Env) {
if (auto *V = dyn_cast<VarDecl>(&D))
- if (V->hasGlobalStorage())
- Vars.insert(V);
-}
-
-static void getFieldsAndGlobalVars(const Decl &D,
- llvm::DenseSet<const FieldDecl *> &Fields,
- llvm::DenseSet<const VarDecl *> &Vars) {
- insertIfGlobal(D, Fields, Vars);
- if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D))
- for (const auto *B : Decomp->bindings())
- if (auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding()))
- // FIXME: should we be using `E->getFoundDecl()`?
- if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
- Fields.insert(FD);
-}
-
-/// Traverses `S` and inserts into `Vars` any global storage values that are
-/// declared in or referenced from sub-statements.
-static void getFieldsAndGlobalVars(const Stmt &S,
- llvm::DenseSet<const FieldDecl *> &Fields,
- llvm::DenseSet<const VarDecl *> &Vars) {
- for (auto *Child : S.children())
+ initGlobalVar(*V, Env);
+}
+
+/// Initializes global storage values that are declared or referenced from
+/// sub-statements of `S`.
+// FIXME: Add support for resetting globals after function calls to enable
+// the implementation of sound analyses.
+static void initGlobalVars(const Stmt &S, Environment &Env) {
+ for (auto *Child : S.children()) {
if (Child != nullptr)
- getFieldsAndGlobalVars(*Child, Fields, Vars);
+ initGlobalVars(*Child, Env);
+ }
if (auto *DS = dyn_cast<DeclStmt>(&S)) {
- if (DS->isSingleDecl())
- getFieldsAndGlobalVars(*DS->getSingleDecl(), Fields, Vars);
- else
+ if (DS->isSingleDecl()) {
+ initGlobalVar(*DS->getSingleDecl(), Env);
+ } else {
for (auto *D : DS->getDeclGroup())
- getFieldsAndGlobalVars(*D, Fields, Vars);
+ initGlobalVar(*D, Env);
+ }
} else if (auto *E = dyn_cast<DeclRefExpr>(&S)) {
- insertIfGlobal(*E->getDecl(), Fields, Vars);
+ initGlobalVar(*E->getDecl(), Env);
} else if (auto *E = dyn_cast<MemberExpr>(&S)) {
- // FIXME: should we be using `E->getFoundDecl()`?
- const ValueDecl *VD = E->getMemberDecl();
- insertIfGlobal(*VD, Fields, Vars);
- if (const auto *FD = dyn_cast<FieldDecl>(VD))
- Fields.insert(FD);
- }
-}
-
-// FIXME: Add support for resetting globals after function calls to enable
-// the implementation of sound analyses.
-void Environment::initVars(llvm::DenseSet<const VarDecl *> Vars) {
- for (const VarDecl *D : Vars) {
- if (getStorageLocation(*D, SkipPast::None) != nullptr)
- continue;
- auto &Loc = createStorageLocation(*D);
- setStorageLocation(*D, Loc);
- if (auto *Val = createValue(D->getType()))
- setValue(Loc, *Val);
+ initGlobalVar(*E->getMemberDecl(), Env);
}
}
@@ -234,27 +216,7 @@ Environment::Environment(DataflowAnalysisContext &DACtx,
if (const auto *FuncDecl = dyn_cast<FunctionDecl>(&DeclCtx)) {
assert(FuncDecl->getBody() != nullptr);
-
- llvm::DenseSet<const FieldDecl *> Fields;
- llvm::DenseSet<const VarDecl *> Vars;
-
- // Look for global variable references in the constructor-initializers.
- if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(&DeclCtx)) {
- for (const auto *Init : CtorDecl->inits()) {
- if (const auto *M = Init->getAnyMember())
- Fields.insert(M);
- const Expr *E = Init->getInit();
- assert(E != nullptr);
- getFieldsAndGlobalVars(*E, Fields, Vars);
- }
- }
- getFieldsAndGlobalVars(*FuncDecl->getBody(), Fields, Vars);
-
- initVars(Vars);
- // These have to be set before the lines that follow to ensure that create*
- // work correctly for structs.
- DACtx.addFieldsReferencedInScope(std::move(Fields));
-
+ initGlobalVars(*FuncDecl->getBody(), *this);
for (const auto *ParamDecl : FuncDecl->parameters()) {
assert(ParamDecl != nullptr);
auto &ParamLoc = createStorageLocation(*ParamDecl);
@@ -281,6 +243,15 @@ Environment::Environment(DataflowAnalysisContext &DACtx,
setValue(*ThisPointeeLoc, *ThisPointeeVal);
}
}
+
+ // Look for global variable references in the constructor-initializers.
+ if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(&DeclCtx)) {
+ for (const auto *Init : CtorDecl->inits()) {
+ const Expr *E = Init->getInit();
+ assert(E != nullptr);
+ initGlobalVars(*E, *this);
+ }
+ }
}
bool Environment::canDescend(unsigned MaxDepth,
@@ -327,24 +298,10 @@ void Environment::pushCallInternal(const FunctionDecl *FuncDecl,
ArrayRef<const Expr *> Args) {
CallStack.push_back(FuncDecl);
- // FIXME: Share this code with the constructor, rather than duplicating it.
- llvm::DenseSet<const FieldDecl *> Fields;
- llvm::DenseSet<const VarDecl *> Vars;
- // Look for global variable references in the constructor-initializers.
- if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FuncDecl)) {
- for (const auto *Init : CtorDecl->inits()) {
- if (const auto *M = Init->getAnyMember())
- Fields.insert(M);
- const Expr *E = Init->getInit();
- assert(E != nullptr);
- getFieldsAndGlobalVars(*E, Fields, Vars);
- }
- }
- getFieldsAndGlobalVars(*FuncDecl->getBody(), Fields, Vars);
- initVars(Vars);
- DACtx->addFieldsReferencedInScope(std::move(Fields));
+ // FIXME: In order to allow the callee to reference globals, we probably need
+ // to call `initGlobalVars` here in some way.
- const auto *ParamIt = FuncDecl->param_begin();
+ auto ParamIt = FuncDecl->param_begin();
// FIXME: Parameters don't always map to arguments 1:1; examples include
// overloaded operators implemented as member functions, and parameter packs.
@@ -613,7 +570,7 @@ void Environment::setValue(const StorageLocation &Loc, Value &Val) {
const QualType Type = AggregateLoc.getType();
assert(Type->isStructureOrClassType() || Type->isUnionType());
- for (const FieldDecl *Field : DACtx->getReferencedFields(Type)) {
+ for (const FieldDecl *Field : getObjectFields(Type)) {
assert(Field != nullptr);
StorageLocation &FieldLoc = AggregateLoc.getChild(*Field);
MemberLocToStruct[&FieldLoc] = std::make_pair(StructVal, Field);
@@ -727,8 +684,10 @@ Value *Environment::createValueUnlessSelfReferential(
if (Type->isStructureOrClassType() || Type->isUnionType()) {
CreatedValuesCount++;
+ // FIXME: Initialize only fields that are accessed in the context that is
+ // being analyzed.
llvm::DenseMap<const ValueDecl *, Value *> FieldValues;
- for (const FieldDecl *Field : DACtx->getReferencedFields(Type)) {
+ for (const FieldDecl *Field : getObjectFields(Type)) {
assert(Field != nullptr);
QualType FieldType = Field->getType();
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 465dbc9abeff..32e9d6f12e44 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -283,7 +283,7 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
} else if (auto *VD = B->getHoldingVar()) {
// Holding vars are used to back the BindingDecls of tuple-like
// types. The holding var declarations appear *after* this statement,
- // so we have to create a location for them here to share with `B`. We
+ // so we have to create a location or them here to share with `B`. We
// don't visit the binding, because we know it will be a DeclRefExpr
// to `VD`.
auto &VDLoc = Env.createStorageLocation(*VD);
diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
index 5e55e1be8e47..b237f3b83759 100644
--- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
@@ -57,8 +57,6 @@ TEST_F(EnvironmentTest, CreateValueRecursiveType) {
bool X;
Recursive *R;
};
- // Use both fields to force them to be created with `createValue`.
- void Usage(Recursive R) { (void)R.X; (void)R.R; }
)cc";
auto Unit =
@@ -76,15 +74,11 @@ TEST_F(EnvironmentTest, CreateValueRecursiveType) {
const QualType *Ty = selectFirst<QualType>("target", Results);
const FieldDecl *R = selectFirst<FieldDecl>("field-r", Results);
ASSERT_TRUE(Ty != nullptr && !Ty->isNull());
- ASSERT_THAT(R, NotNull());
-
- Results = match(functionDecl(hasName("Usage")).bind("fun"), Context);
- const auto *Fun = selectFirst<FunctionDecl>("fun", Results);
- ASSERT_THAT(Fun, NotNull());
+ ASSERT_TRUE(R != nullptr);
// Verify that the struct and the field (`R`) with first appearance of the
// type is created successfully.
- Environment Env(DAContext, *Fun);
+ Environment Env(DAContext);
Value *Val = Env.createValue(*Ty);
ASSERT_NE(Val, nullptr);
StructValue *SVal = clang::dyn_cast<StructValue>(Val);
diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
index e38826cfbe27..c72e8e47dd8e 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -134,11 +134,6 @@ template <typename AnalysisT> struct AnalysisInputs {
ASTBuildVirtualMappedFiles = std::move(Arg);
return std::move(*this);
}
- AnalysisInputs<AnalysisT> &&
- withContextSensitivity() && {
- EnableContextSensitivity = true;
- return std::move(*this);
- }
/// Required. Input code that is analyzed.
llvm::StringRef Code;
@@ -164,9 +159,6 @@ template <typename AnalysisT> struct AnalysisInputs {
ArrayRef<std::string> ASTBuildArgs = {};
/// Optional. Options for building the AST context.
tooling::FileContentMappings ASTBuildVirtualMappedFiles = {};
- /// Enables context-sensitive analysis when constructing the
- /// `DataflowAnalysisContext`.
- bool EnableContextSensitivity = false;
};
/// Returns assertions based on annotations that are present after statements in
@@ -230,9 +222,7 @@ checkDataflow(AnalysisInputs<AnalysisT> AI,
auto &CFCtx = *MaybeCFCtx;
// Initialize states for running dataflow analysis.
- DataflowAnalysisContext DACtx(
- std::make_unique<WatchedLiteralsSolver>(),
- {/*EnableContextSensitiveAnalysis=*/AI.EnableContextSensitivity});
+ DataflowAnalysisContext DACtx(std::make_unique<WatchedLiteralsSolver>());
Environment InitEnv(DACtx, *Target);
auto Analysis = AI.MakeAnalysis(Context, InitEnv);
std::function<void(const CFGElement &,
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 68de3865fec0..a9b1f42f2036 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -16,7 +16,6 @@
#include "clang/Analysis/FlowSensitive/Value.h"
#include "clang/Basic/LangStandard.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Testing/Support/Error.h"
@@ -40,22 +39,17 @@ void runDataflow(llvm::StringRef Code, Matcher Match,
LangStandard::Kind Std = LangStandard::lang_cxx17,
llvm::StringRef TargetFun = "target") {
using ast_matchers::hasName;
- llvm::SmallVector<std::string, 3> ASTBuildArgs = {
- "-fsyntax-only", "-fno-delayed-template-parsing",
- "-std=" +
- std::string(LangStandard::getLangStandardForKind(Std).getName())};
- auto AI =
- AnalysisInputs<NoopAnalysis>(Code, hasName(TargetFun),
- [&Options](ASTContext &C, Environment &) {
- return NoopAnalysis(C, Options);
- })
- .withASTBuildArgs(ASTBuildArgs);
- if (Options.BuiltinTransferOpts &&
- Options.BuiltinTransferOpts->ContextSensitiveOpts)
- AI = std::move(AI).withContextSensitivity();
ASSERT_THAT_ERROR(
checkDataflow<NoopAnalysis>(
- std::move(AI),
+ AnalysisInputs<NoopAnalysis>(Code, hasName(TargetFun),
+ [Options](ASTContext &C, Environment &) {
+ return NoopAnalysis(C, Options);
+ })
+ .withASTBuildArgs(
+ {"-fsyntax-only", "-fno-delayed-template-parsing",
+ "-std=" +
+ std::string(LangStandard::getLangStandardForKind(Std)
+ .getName())}),
/*VerifyResults=*/
[&Match](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
&Results,
@@ -157,7 +151,6 @@ TEST(TransferTest, StructVarDecl) {
void target() {
A Foo;
- (void)Foo.Bar;
// [[p]]
}
)";
@@ -205,7 +198,6 @@ TEST(TransferTest, StructVarDeclWithInit) {
void target() {
A Foo = Gen();
- (void)Foo.Bar;
// [[p]]
}
)";
@@ -246,13 +238,11 @@ TEST(TransferTest, StructVarDeclWithInit) {
TEST(TransferTest, ClassVarDecl) {
std::string Code = R"(
class A {
- public:
int Bar;
};
void target() {
A Foo;
- (void)Foo.Bar;
// [[p]]
}
)";
@@ -346,10 +336,6 @@ TEST(TransferTest, SelfReferentialReferenceVarDecl) {
void target() {
A &Foo = getA();
- (void)Foo.Bar.FooRef;
- (void)Foo.Bar.FooPtr;
- (void)Foo.Bar.BazRef;
- (void)Foo.Bar.BazPtr;
// [[p]]
}
)";
@@ -492,10 +478,6 @@ TEST(TransferTest, SelfReferentialPointerVarDecl) {
void target() {
A *Foo = getA();
- (void)Foo->Bar->FooRef;
- (void)Foo->Bar->FooPtr;
- (void)Foo->Bar->BazRef;
- (void)Foo->Bar->BazPtr;
// [[p]]
}
)";
@@ -909,7 +891,7 @@ TEST(TransferTest, StructParamDecl) {
};
void target(A Foo) {
- (void)Foo.Bar;
+ (void)0;
// [[p]]
}
)";
@@ -1070,9 +1052,6 @@ TEST(TransferTest, DerivedBaseMemberClass) {
int APrivate;
public:
int APublic;
-
- private:
- friend void target();
};
class B : public A {
@@ -1081,20 +1060,10 @@ TEST(TransferTest, DerivedBaseMemberClass) {
int BProtected;
private:
int BPrivate;
-
- private:
- friend void target();
};
void target() {
B Foo;
- (void)Foo.ADefault;
- (void)Foo.AProtected;
- (void)Foo.APrivate;
- (void)Foo.APublic;
- (void)Foo.BDefault;
- (void)Foo.BProtected;
- (void)Foo.BPrivate;
// [[p]]
}
)";
@@ -1233,7 +1202,6 @@ TEST(TransferTest, DerivedBaseMemberStructDefault) {
void target() {
B Foo;
- (void)Foo.Bar;
// [[p]]
}
)";
@@ -1557,11 +1525,7 @@ TEST(TransferTest, UnionThisMember) {
int Bar;
void target() {
- A a;
- // Mention the fields to ensure they're included in the analysis.
- (void)a.Foo;
- (void)a.Bar;
- // [[p]]
+ (void)0; // [[p]]
}
};
)";
@@ -1813,7 +1777,6 @@ TEST(TransferTest, TemporaryObject) {
void target() {
A Foo = A();
- (void)Foo.Bar;
// [[p]]
}
)";
@@ -1851,7 +1814,6 @@ TEST(TransferTest, ElidableConstructor) {
void target() {
A Foo = A();
- (void)Foo.Bar;
// [[p]]
}
)";
@@ -1889,7 +1851,6 @@ TEST(TransferTest, AssignmentOperator) {
void target() {
A Foo;
A Bar;
- (void)Foo.Baz;
// [[p1]]
Foo = Bar;
// [[p2]]
@@ -1952,7 +1913,6 @@ TEST(TransferTest, CopyConstructor) {
void target() {
A Foo;
- (void)Foo.Baz;
A Bar = Foo;
// [[p]]
}
@@ -1998,7 +1958,6 @@ TEST(TransferTest, CopyConstructorWithParens) {
void target() {
A Foo;
- (void)Foo.Baz;
A Bar((A(Foo)));
// [[p]]
}
@@ -2059,7 +2018,6 @@ TEST(TransferTest, MoveConstructor) {
void target() {
A Foo;
A Bar;
- (void)Foo.Baz;
// [[p1]]
Foo = std::move(Bar);
// [[p2]]
More information about the cfe-commits
mailing list