forked from OSchip/llvm-project
[Analyzer] Allow creation of stack frame for functions without definition
Retrieving the parameter location of functions was disabled because it may causes crashes due to the fact that functions may have multiple declarations and without definition it is difficult to ensure that always the same declration is used. Now parameters are stored in `ParamRegions` which are independent of the declaration of the function, therefore the same parameters always have the same regions, independently of the function declaration used actually. This allows us to remove the limitation described above. Differential Revision: https://reviews.llvm.org/D80286
This commit is contained in:
parent
98db1f990f
commit
5419a31215
|
@ -172,23 +172,9 @@ AnalysisDeclContext *CallEvent::getCalleeAnalysisDeclContext() const {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
} // 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\(\)'$}}}}
|
||||
}
|
||||
|
||||
|
|
|
@ -890,12 +890,9 @@ class C {
|
|||
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
|
||||
}
|
||||
};
|
||||
|
@ -914,16 +911,11 @@ void test(int coin) {
|
|||
// 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}}
|
||||
// expected-warning@-2{{TRUE}}
|
||||
#else
|
||||
// expected-warning@-5{{UNKNOWN}}
|
||||
#endif
|
||||
#else
|
||||
// expected-warning@-8{{UNKNOWN}}
|
||||
// expected-warning@-4{{UNKNOWN}}
|
||||
#endif
|
||||
} else {
|
||||
// The destructor is not called on this branch.
|
||||
|
|
|
@ -16,6 +16,15 @@ namespace ento {
|
|||
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();
|
||||
|
@ -29,6 +38,7 @@ class ParamRegionTestConsumer : public ExprEngineConsumer {
|
|||
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()) {
|
||||
|
@ -37,6 +47,7 @@ class ParamRegionTestConsumer : public ExprEngineConsumer {
|
|||
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()) {
|
||||
|
@ -45,6 +56,7 @@ class ParamRegionTestConsumer : public ExprEngineConsumer {
|
|||
assert(isa<NonParamVarRegion>(Reg));
|
||||
else
|
||||
assert(isa<ParamVarRegion>(Reg));
|
||||
checkForSameParamRegions(MRMgr, SFC, P);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +83,10 @@ public:
|
|||
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;
|
||||
};
|
||||
|
@ -90,7 +105,10 @@ TEST(ParamRegion, ParamRegionTest) {
|
|||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue