From 19ed6748ea2ff303040702cc6043b9a0c6ca9ce1 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Fri, 28 Sep 2012 17:15:25 +0000 Subject: [PATCH] [analyzer] Handle inlined constructors for rvalue temporaries correctly. Previously the analyzer treated all inlined constructors like lvalues, setting the value of the CXXConstructExpr to the newly-constructed region. However, some CXXConstructExprs behave like rvalues -- in particular, the implicit copy constructor into a pass-by-value argument. In this case, we want only the /contents/ of a temporary object to be passed, so that we can use the same "copy each argument into the parameter region" algorithm that we use for scalar arguments. This may change when we start modeling destructors of temporaries, but for now this is the last part of . llvm-svn: 164830 --- clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 9 ++++++++- clang/test/Analysis/array-struct-region.cpp | 6 ------ clang/test/Analysis/ctor-inlining.mm | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index eb5395e..2e460b7 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -160,7 +160,14 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) { svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx); SVal ThisV = state->getSVal(This); - // Always bind the region to the CXXConstructExpr. + // If the constructed object is a prvalue, get its bindings. + // Note that we have to be careful here because constructors embedded + // in DeclStmts are not marked as lvalues. + if (!CCE->isGLValue()) + if (const MemRegion *MR = ThisV.getAsRegion()) + if (isa(MR)) + ThisV = state->getSVal(cast(ThisV)); + state = state->BindExpr(CCE, callerCtx, ThisV); } } diff --git a/clang/test/Analysis/array-struct-region.cpp b/clang/test/Analysis/array-struct-region.cpp index 22fbf2f..e7fbe4d 100644 --- a/clang/test/Analysis/array-struct-region.cpp +++ b/clang/test/Analysis/array-struct-region.cpp @@ -61,12 +61,6 @@ int getAssignedField(struct S s) { void testArgument() { clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}} -#if __cplusplus - // FIXME: Passing the struct by value seems to be confusing C++. - // Possibly related to . - // expected-warning@-4{{UNKNOWN}} -#endif - clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}} } diff --git a/clang/test/Analysis/ctor-inlining.mm b/clang/test/Analysis/ctor-inlining.mm index 918de0a..ac963e5 100644 --- a/clang/test/Analysis/ctor-inlining.mm +++ b/clang/test/Analysis/ctor-inlining.mm @@ -103,3 +103,17 @@ namespace TemporaryConstructor { return; } } + + +namespace ConstructorUsedAsRValue { + using TemporaryConstructor::BoolWrapper; + + bool extractValue(BoolWrapper b) { + return b.value; + } + + void test() { + bool result = extractValue(BoolWrapper()); + clang_analyzer_eval(result); // expected-warning{{TRUE}} + } +} -- 2.7.4