forked from OSchip/llvm-project
For forward-declared static inline functions, delay CFG-based warnings until we
encounter a definition. llvm-svn: 99243
This commit is contained in:
parent
bb6f5af4a4
commit
a3ab0d7666
|
@ -353,8 +353,14 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
|
|||
|
||||
// Only analyze 'static inline' functions when explicitly asked.
|
||||
if (!analyzeStaticInline && FD->isInlineSpecified() &&
|
||||
FD->getStorageClass() == FunctionDecl::Static)
|
||||
return;
|
||||
FD->getStorageClass() == FunctionDecl::Static) {
|
||||
FD = FD->getCanonicalDecl();
|
||||
VisitFlag &visitFlag = VisitedFD[FD];
|
||||
if (visitFlag == Pending)
|
||||
visitFlag = Visited;
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const Stmt *Body = D->getBody();
|
||||
|
@ -397,18 +403,26 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
|
|||
if (const DeclRefExpr *DR =
|
||||
dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenCasts()))
|
||||
if (const FunctionDecl *calleeD =
|
||||
dyn_cast<FunctionDecl>(DR->getDecl()))
|
||||
dyn_cast<FunctionDecl>(DR->getDecl())) {
|
||||
calleeD = calleeD->getCanonicalDecl();
|
||||
if (calleeD->isInlineSpecified() &&
|
||||
calleeD->getStorageClass() == FunctionDecl::Static) {
|
||||
// Have we analyzed this static inline function before?
|
||||
unsigned &visited = VisitedFD[calleeD];
|
||||
if (!visited) {
|
||||
VisitFlag &visitFlag = VisitedFD[calleeD];
|
||||
if (visitFlag == NotVisited) {
|
||||
// Mark the callee visited prior to analyzing it
|
||||
// so we terminate in case of recursion.
|
||||
visited = 1;
|
||||
IssueWarnings(DefaultPolicy, calleeD, QualType(), true);
|
||||
if (calleeD->getBody()) {
|
||||
visitFlag = Visited;
|
||||
IssueWarnings(DefaultPolicy, calleeD, QualType(), true);
|
||||
}
|
||||
else {
|
||||
// Delay warnings until we encounter the definition.
|
||||
visitFlag = Pending;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,8 @@ private:
|
|||
Sema &S;
|
||||
Policy DefaultPolicy;
|
||||
|
||||
llvm::DenseMap<const FunctionDecl*, unsigned> VisitedFD;
|
||||
enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 };
|
||||
llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD;
|
||||
|
||||
public:
|
||||
AnalysisBasedWarnings(Sema &s);
|
||||
|
|
|
@ -227,12 +227,15 @@ void test33() {
|
|||
// when they are used.
|
||||
static inline int si_has_missing_return() {} // no-warning
|
||||
static inline int si_has_missing_return_2() {}; // expected-warning{{control reaches end of non-void function}}
|
||||
static inline int si_forward();
|
||||
static inline int si_has_missing_return_3(int x) {
|
||||
if (x)
|
||||
return si_has_missing_return_3(x+1);
|
||||
} // expected-warning{{control may reach end of non-void function}}
|
||||
|
||||
int test_static_inline(int x) {
|
||||
si_forward();
|
||||
return x ? si_has_missing_return_2() : si_has_missing_return_3(x);
|
||||
}
|
||||
static inline int si_forward() {} // expected-warning{{control reaches end of non-void function}}
|
||||
|
||||
|
|
Loading…
Reference in New Issue