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]] _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits