Index: clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -103,8 +103,9 @@ static const Expr * LookThroughTransitiveAssignmentsAndCommaOperators(const Expr *Ex) { while (Ex) { + Ex = Ex->IgnoreParenCasts(); const BinaryOperator *BO = - dyn_cast(Ex->IgnoreParenCasts()); + dyn_cast(Ex); if (!BO) break; BinaryOperatorKind Op = BO->getOpcode(); @@ -332,7 +333,6 @@ // This is a common form of defensive programming. const Expr *RHS = LookThroughTransitiveAssignmentsAndCommaOperators(B->getRHS()); - RHS = RHS->IgnoreParenCasts(); QualType T = VD->getType(); if (T.isVolatileQualified()) @@ -416,7 +416,7 @@ return; if (const DeclRefExpr *DRE = - dyn_cast(E->IgnoreParenCasts())) + dyn_cast(E)) if (const VarDecl *VD = dyn_cast(DRE->getDecl())) { // Special case: check for initialization from constant // variables. @@ -450,8 +450,9 @@ bool isConstant(const InitListExpr *Candidate) const { // We consider init list to be constant if each member of the list can be // interpreted as constant. - return llvm::all_of(Candidate->inits(), - [this](const Expr *Init) { return isConstant(Init); }); + return llvm::all_of(Candidate->inits(), [this](const Expr *Init) { + return isConstant(Init->IgnoreParenCasts()); + }); } /// Return true if the given expression can be interpreted as constant @@ -461,7 +462,7 @@ return true; // We should also allow defensive initialization of structs, i.e. { 0 } - if (const auto *ILE = dyn_cast(E->IgnoreParenCasts())) { + if (const auto *ILE = dyn_cast(E)) { return isConstant(ILE); } Index: clang/test/Analysis/Inputs/expected-plists/objc-arc.m.plist =================================================================== --- clang/test/Analysis/Inputs/expected-plists/objc-arc.m.plist +++ clang/test/Analysis/Inputs/expected-plists/objc-arc.m.plist @@ -432,7 +432,7 @@ line139 - col13 + col35 file0 @@ -500,7 +500,7 @@ line144 - col13 + col33 file0 @@ -568,7 +568,7 @@ line145 - col13 + col26 file0 @@ -636,7 +636,7 @@ line146 - col13 + col33 file0 @@ -1046,7 +1046,7 @@ line150 - col19 + col48 file0 @@ -1114,7 +1114,7 @@ line151 - col21 + col52 file0 @@ -1182,7 +1182,7 @@ line152 - col19 + col39 file0 @@ -1250,7 +1250,7 @@ line153 - col21 + col43 file0 Index: clang/test/Analysis/dead-stores.cpp =================================================================== --- clang/test/Analysis/dead-stores.cpp +++ clang/test/Analysis/dead-stores.cpp @@ -12,6 +12,10 @@ // RUN: -analyzer-checker=deadcode.DeadStores -Wno-unreachable-code \ // RUN: -verify=non-nested,nested %s +// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++17 \ +// RUN: -analyzer-checker=deadcode.DeadStores -Wno-unreachable-code \ +// RUN: -verify=non-nested,nested %s + //===----------------------------------------------------------------------===// // Basic dead store checking (but in C++ mode). //===----------------------------------------------------------------------===// @@ -52,6 +56,17 @@ return x; } +class TestConstructor { +public: + TestConstructor(int &y); +}; +void copy(int x) { + TestConstructor tc1 = x; // no-warning + TestConstructor tc2 = TestConstructor(x); // no-warning + TestConstructor tc3 = (TestConstructor(x)); // no-warning + TestConstructor tc4 = (TestConstructor)(x); // no-warning +} + //===----------------------------------------------------------------------===// // Dead store checking involving CXXTemporaryExprs //===----------------------------------------------------------------------===//