Create CFG for initializers and perform analysis based warnings on global variables
Details
Diff Detail
- Repository
 - rG LLVM Github Monorepo
 - Build Status
 Buildable 36904 Build 36903: arc lint + arc unit 
Event Timeline
| clang/include/clang/Sema/AnalysisBasedWarnings.h | ||
|---|---|---|
| 117 | Fix indentation.  | |
| clang/lib/Sema/AnalysisBasedWarnings.cpp | ||
| 2002 | Should PossiblyUnreachableDiags be const? Also, fix indentation.  | |
| 2010 | How about returning early if PossiblyUnreachableDiags here is empty? That'll avoid putting the entire logic of this function in the true branch.  | |
| 2026 | getCFGReachablityAnalysis has a typo. It's missing an 'i'. Consider fixing this in a separate patch.  | |
| 2046 | Rewrite this as the else clause for if (AC.getCFG())? In the current structure, it's not immediately clear that flushDiagnostics is called iff AC.getCFG() fails to return a valid CFG. Upon further reading, this seems to be refactored from another function below so it probably makes sense to leave it as-is.  | |
| clang/include/clang/Sema/AnalysisBasedWarnings.h | ||
|---|---|---|
| 104 | git-clang-format HEAD~<number of commits> The formal parameter should be abbreviated, maybe PUD?  | |
| 116 | How about making this a proper method of AnalysisBasedWarnings rather than a free floating function that's only ever called from other methods of AnalysisBasedWarnings? That way you don't have to pass in a Sema.  | |
| clang/lib/Analysis/AnalysisDeclContext.cpp | ||
| 124 | The const_cast doesn't look necessary here. Is it?  | |
| clang/lib/Sema/AnalysisBasedWarnings.cpp | ||
| 2007 | having the full namespace spelled out here in the definition smells funny. Is there a pair of namespace blocks below for clang and sema where the definition of emitPossiblyUnreachableDiags could be moved into? Actually looking at the file, I see you simply matched the existing style, but line 49 currently has a using statement that should inject the clang namespace into the current scope. That's why you see sema:: used in other places in this translation unit without the clang namespace prefix. The whole file should remove the clang:: prefixes or additionally replace the using statement with explicit namespace blocks.  | |
| 2257 | PUD  | |
| 2272 | If you make emitPossiblyUnreachableDiags then it doesn't need all the prefixes.  | |
| clang/lib/Sema/SemaDeclCXX.cpp | ||
| 347 | Use punctuation in your comments.  | |
| clang/lib/Sema/SemaExpr.cpp | ||
| 16679 | Punctuation.  | |
| clang/test/Sema/warn-unreachable-warning-var-decl.cpp | ||
| 40–41 | ok and also ok can probably be removed?  | |
| clang/lib/Analysis/AnalysisDeclContext.cpp | ||
|---|---|---|
| 124 | VD->getInit returns a const Expr *. In order to remove the const_cast I would need to make getBody() const and every call to getBody(). The change required to add const seemed too large to be included in this patch.  | |
| clang/lib/Sema/SemaDeclCXX.cpp | ||
|---|---|---|
| 340 | We may need to delay the diagnostics here until the default argument is *used*: if a default argument references a template instantiation, the instantiation is not performed until that point, which may mean that our semantic checking can't complete correctly until use.  | |
| clang/lib/Sema/SemaExpr.cpp | ||
| 16694 | It's not correct to assume that the last declaration in the context is the right one to be considering here. Instead, you should track whether you're in a variable initializer (and for what) in Sema. Examples: int x = ([]{}(), x); // in C++; last decl is the lambdaint y = (struct Q { int n; }){y}; // in C; last decl is the struct | |
| clang/include/clang/Sema/Sema.h | ||
|---|---|---|
| 1689 | might be nice to return the result, but maybe YAGNI?  | |
| clang/lib/Sema/AnalysisBasedWarnings.cpp | ||
|---|---|---|
| 2009 | is clang namespace required here?  | |
| clang/lib/Sema/SemaDeclCXX.cpp | ||
|---|---|---|
| 340 | Currently this patch really only works with globals. There are many places where the following check is made instead of calling ParseInitializer. These should probably be rewritten into a single function and do something similar with pushing/popping declarations. Not sure if that change should be made in this patch or not. if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
            Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
            DefArgResult = ParseBraceInitializer();
          } else
            DefArgResult = ParseAssignmentExpression(); | |
| clang/include/clang/Sema/Sema.h | ||
|---|---|---|
| 1684–1686 | I don't think a simple list of these can work. Consider a case like: auto x = [] {
  // something with a runtime diagnostic
};Here, we'll have a DeclForInitializer set, so we'll suppress warnings on the body of the lambda, but we shouldn't: the body of the lambda is a completely different evaluation context from the initialization of the variable x. Can you store the declaration on the ExpressionEvaluationContextRecord instead of storing a list of them directly on Sema? (You shouldn't need a list there, just a single pointer should work, since we can't parse two nested initializers without an intervening evaluation context.)  | |
| clang/lib/Sema/AnalysisBasedWarnings.cpp | ||
| 2015 | Please capitalize the names of variables.  | |
| clang/lib/Sema/SemaExpr.cpp | ||
| 16678–16695 | Please get rid of the pre-existing hacky use of ManglingContextDecl here and move this into the getDeclForInitializer block below.  | |
| clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp | ||
|---|---|---|
| 360 | These new warnings seem valid.  | |
| clang/include/clang/Parse/Parser.h | ||
|---|---|---|
| 1873 | This should be done by calling a function on Sema (add an ActOnStartDeclInitializer or similar), not by directly modifying Sema's internal state.  | |
| 1880 | Please add an assertion when you first set this that the old value was null.  | |
| clang/lib/Sema/AnalysisBasedWarnings.cpp | ||
| 2263 | Consider grabbing VarDeclPossiblyUnreachableDiags[VD] first and avoiding constructing the AnalysisDeclContext at all in the (presumably overwhelmingly common case) that there are no such diagnostics.  | |
| clang/lib/Sema/SemaDecl.cpp | ||
| 11853 | We should (presumably) only do this for file-scope variables. The initializers for block-scope variables will be checked when checking the enclosing function (if the variables' declarations are reachable at all).  | |
| clang/lib/Sema/SemaExpr.cpp | ||
| 4884 | We should only do this once, when we instantiate the default argument, rather than once each time we use it. (Move this up to just before line 4856?)  | |
| 16670 | This call to getCurFunctionOrMethodDecl() is wrong; it will skip over lambda-expressions. (This is why you're still seeing diagnostics in file-scope lambdas.) Something like this should work: if (Stmts.empty()) {
  Diag(Loc, PD);
  return true;
}
if (FunctionScopeInfo *FSI = getCurFunction()) {
  FunctionScopes.back()->PossiblyUnreachableDiags.push_back(
      PossiblyUnreachableDiag(PD, Loc, Stmts));
  return true;
}
// [handle VarDecl case] | |
| 16680–16682 | No braces here please. Also, this appears to be wrong: we want the declaration with the initializer (which is always VD), not the definition (which might be a different declaration for a static data member), don't we?  | |
| 16690 | What does this fixme mean?  | |
| clang/test/SemaTemplate/instantiate-static-var.cpp | ||
| 9 | We should not warn here (because this initializer is required to be a constant expression).  | |
This should be done by calling a function on Sema (add an ActOnStartDeclInitializer or similar), not by directly modifying Sema's internal state.