Refactor CFG-based warnings in Sema to be run by a worked object called AnalysisBasedWarnings.
This object controls when the warnings are executed, allowing the client code
in Sema to selectively disable warnings as needed.
Centralizing the logic for analysis-based warnings allows us to optimize
when and how they are run.
Along the way, remove the redundant logic for the 'check fall-through' warning
for blocks; now the same logic is used for both blocks and functions.
llvm-svn: 99085
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index bab3d98..e11e161 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14,7 +14,7 @@
#include "Sema.h"
#include "SemaInit.h"
#include "Lookup.h"
-#include "clang/Analysis/AnalysisContext.h"
+#include "AnalysisBasedWarnings.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -4259,9 +4259,6 @@
Decl *dcl = D.getAs<Decl>();
Stmt *Body = BodyArg.takeAs<Stmt>();
- // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
- // explosion for destrutors that can result and the compile time hit.
- AnalysisContext AC(dcl, false);
FunctionDecl *FD = 0;
FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl);
if (FunTmpl)
@@ -4269,14 +4266,16 @@
else
FD = dyn_cast_or_null<FunctionDecl>(dcl);
+ sema::AnalysisBasedWarnings W(*this);
+
if (FD) {
FD->setBody(Body);
- if (FD->isMain())
+ if (FD->isMain()) {
// C and C++ allow for main to automagically return 0.
// Implements C++ [basic.start.main]p5 and C99 5.1.2.2.3.
FD->setHasImplicitReturnZero(true);
- else
- CheckFallThroughForFunctionDef(FD, Body, AC);
+ W.disableCheckFallThrough();
+ }
if (!FD->isInvalidDecl())
DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
@@ -4288,9 +4287,7 @@
} else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
assert(MD == getCurMethodDecl() && "Method parsing confused");
MD->setBody(Body);
- CheckFallThroughForFunctionDef(MD, Body, AC);
MD->setEndLoc(Body->getLocEnd());
-
if (!MD->isInvalidDecl())
DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
} else {
@@ -4343,16 +4340,14 @@
}
if (Body) {
- CheckUnreachable(AC);
-
// C++ constructors that have function-try-blocks can't have return
// statements in the handlers of that block. (C++ [except.handle]p14)
// Verify this.
if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body))
DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
- // Verify that that gotos and switch cases don't jump into scopes illegally.
- // Verify that that gotos and switch cases don't jump into scopes illegally.
+ // Verify that that gotos and switch cases don't jump into scopes illegally.
+ // Verify that that gotos and switch cases don't jump into scopes illegally.
if (FunctionNeedsScopeChecking() && !hasAnyErrorsInThisFunction())
DiagnoseInvalidJumps(Body);
@@ -4365,7 +4360,20 @@
// deletion in some later function.
if (PP.getDiagnostics().hasErrorOccurred())
ExprTemporaries.clear();
-
+ else if (!isa<FunctionTemplateDecl>(dcl)) {
+ // Since the body is valid, issue any analysis-based warnings that are
+ // enabled.
+ QualType ResultType;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(dcl)) {
+ ResultType = FD->getResultType();
+ }
+ else {
+ ObjCMethodDecl *MD = cast<ObjCMethodDecl>(dcl);
+ ResultType = MD->getResultType();
+ }
+ W.IssueWarnings(dcl);
+ }
+
assert(ExprTemporaries.empty() && "Leftover temporaries in function");
}