if (!D)
return nullptr;
- // TODO: For now we skip functions without definitions, even if we have
- // our own getDecl(), because it's hard to find out which re-declaration
- // is going to be used, and usually clients don't really care about this
- // situation because there's a loss of precision anyway because we cannot
- // inline the call.
- RuntimeDefinition RD = getRuntimeDefinition();
- if (!RD.getDecl())
- return nullptr;
-
AnalysisDeclContext *ADC =
LCtx->getAnalysisDeclContext()->getManager()->getContext(D);
- // TODO: For now we skip virtual functions, because this also rises
- // the problem of which decl to use, but now it's across different classes.
- if (RD.mayHaveOtherDefinitions() || RD.getDecl() != ADC->getDecl())
- return nullptr;
-
return ADC;
}
} // end of anonymous namespace
void test_6() {
- clang_analyzer_explain(conjure_S()); // expected-warning-re{{{{^lazily frozen compound value of temporary object constructed at statement 'conjure_S\(\)'$}}}}
+ clang_analyzer_explain(conjure_S()); // expected-warning-re{{{{^lazily frozen compound value of 1st parameter of function 'clang_analyzer_explain\(\)'$}}}}
clang_analyzer_explain(conjure_S().z); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure_S\(\)'\) for field 'z' of temporary object constructed at statement 'conjure_S\(\)'$}}}}
}
public:
~C() {
glob = 1;
- // FIXME: Why is destructor not inlined in C++17
clang_analyzer_checkInlined(true);
#ifdef TEMPORARY_DTORS
-#if __cplusplus < 201703L
- // expected-warning@-3{{TRUE}}
-#endif
+ // expected-warning@-2{{TRUE}}
#endif
}
};
// temporaries returned from functions, so we took the wrong branch.
coin && is(get()); // no-crash
if (coin) {
- // FIXME: Why is destructor not inlined in C++17
clang_analyzer_eval(glob);
#ifdef TEMPORARY_DTORS
-#if __cplusplus < 201703L
- // expected-warning@-3{{TRUE}}
-#else
- // expected-warning@-5{{UNKNOWN}}
-#endif
+ // expected-warning@-2{{TRUE}}
#else
- // expected-warning@-8{{UNKNOWN}}
+ // expected-warning@-4{{UNKNOWN}}
#endif
} else {
// The destructor is not called on this branch.
namespace {
class ParamRegionTestConsumer : public ExprEngineConsumer {
+ void checkForSameParamRegions(MemRegionManager &MRMgr,
+ const StackFrameContext *SFC,
+ const ParmVarDecl *PVD) {
+ for (const auto *D2: PVD->redecls()) {
+ const auto *PVD2 = cast<ParmVarDecl>(D2);
+ assert(MRMgr.getVarRegion(PVD, SFC) == MRMgr.getVarRegion(PVD2, SFC));
+ }
+ }
+
void performTest(const Decl *D) {
StoreManager &StMgr = Eng.getStoreManager();
MemRegionManager &MRMgr = StMgr.getRegionManager();
assert(isa<NonParamVarRegion>(Reg));
else
assert(isa<ParamVarRegion>(Reg));
+ checkForSameParamRegions(MRMgr, SFC, P);
}
} else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
for (const auto *P : CD->parameters()) {
assert(isa<NonParamVarRegion>(Reg));
else
assert(isa<ParamVarRegion>(Reg));
+ checkForSameParamRegions(MRMgr, SFC, P);
}
} else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
for (const auto *P : MD->parameters()) {
assert(isa<NonParamVarRegion>(Reg));
else
assert(isa<ParamVarRegion>(Reg));
+ checkForSameParamRegions(MRMgr, SFC, P);
}
}
}
TEST(ParamRegion, ParamRegionTest) {
EXPECT_TRUE(
tooling::runToolOnCode(std::make_unique<ParamRegionTestAction>(),
- R"(void foo(int n) {
+ R"(void foo(int n);
+ void baz(int p);
+
+ void foo(int n) {
auto lambda = [n](int m) {
return n + m;
};
void baz(int p) {
S s(p);
- })"));
+ }
+
+ void bar(int l);
+ void baz(int p);)"));
EXPECT_TRUE(
tooling::runToolOnCode(std::make_unique<ParamRegionTestAction>(),
R"(@interface O