aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/AnalysisBasedWarnings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/AnalysisBasedWarnings.cpp')
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp185
1 files changed, 94 insertions, 91 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index df73fc6da3..bd5416f5f7 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -410,6 +410,98 @@ public:
};
}
+static void DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
+ const Expr *E, bool &fixitIssued,
+ bool isAlwaysUninit) {
+ bool isSelfInit = false;
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (isAlwaysUninit) {
+ // Inspect the initializer of the variable declaration which is
+ // being referenced prior to its initialization. We emit
+ // specialized diagnostics for self-initialization, and we
+ // specifically avoid warning about self references which take the
+ // form of:
+ //
+ // int x = x;
+ //
+ // This is used to indicate to GCC that 'x' is intentionally left
+ // uninitialized. Proven code paths which access 'x' in
+ // an uninitialized state after this will still warn.
+ //
+ // TODO: Should we suppress maybe-uninitialized warnings for
+ // variables initialized in this way?
+ if (const Expr *Initializer = VD->getInit()) {
+ if (DRE == Initializer->IgnoreParenImpCasts())
+ return;
+
+ ContainsReference CR(S.Context, DRE);
+ CR.Visit(const_cast<Expr*>(Initializer));
+ isSelfInit = CR.doesContainReference();
+ }
+ if (isSelfInit) {
+ S.Diag(DRE->getLocStart(),
+ diag::warn_uninit_self_reference_in_init)
+ << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
+ } else {
+ S.Diag(DRE->getLocStart(), diag::warn_uninit_var)
+ << VD->getDeclName() << DRE->getSourceRange();
+ }
+ } else {
+ S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var)
+ << VD->getDeclName() << DRE->getSourceRange();
+ }
+ } else {
+ const BlockExpr *BE = cast<BlockExpr>(E);
+ S.Diag(BE->getLocStart(),
+ isAlwaysUninit ? diag::warn_uninit_var_captured_by_block
+ : diag::warn_maybe_uninit_var_captured_by_block)
+ << VD->getDeclName();
+ }
+
+ // Report where the variable was declared when the use wasn't within
+ // the initializer of that declaration.
+ if (!isSelfInit)
+ S.Diag(VD->getLocStart(), diag::note_uninit_var_def)
+ << VD->getDeclName();
+
+ // Only report the fixit once.
+ if (fixitIssued)
+ return;
+
+ fixitIssued = true;
+
+ // Don't issue a fixit if there is already an initializer.
+ if (VD->getInit())
+ return;
+
+ // Suggest possible initialization (if any).
+ const char *initialization = 0;
+ QualType VariableTy = VD->getType().getCanonicalType();
+
+ if (VariableTy->getAs<ObjCObjectPointerType>()) {
+ // Check if 'nil' is defined.
+ if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil")))
+ initialization = " = nil";
+ else
+ initialization = " = 0";
+ }
+ else if (VariableTy->isRealFloatingType())
+ initialization = " = 0.0";
+ else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus)
+ initialization = " = false";
+ else if (VariableTy->isEnumeralType())
+ return;
+ else if (VariableTy->isScalarType())
+ initialization = " = 0";
+
+ if (initialization) {
+ SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
+ S.Diag(loc, diag::note_var_fixit_add_initialization)
+ << FixItHint::CreateInsertion(loc, initialization);
+ }
+}
+
typedef std::pair<const Expr*, bool> UninitUse;
namespace {
@@ -461,98 +553,9 @@ public:
std::sort(vec->begin(), vec->end(), SLocSort());
for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi)
- {
- const bool isAlwaysUninit = vi->second;
- bool isSelfInit = false;
-
- if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(vi->first)) {
- if (isAlwaysUninit) {
- // Inspect the initializer of the variable declaration which is
- // being referenced prior to its initialization. We emit
- // specialized diagnostics for self-initialization, and we
- // specifically avoid warning about self references which take the
- // form of:
- //
- // int x = x;
- //
- // This is used to indicate to GCC that 'x' is intentionally left
- // uninitialized. Proven code paths which access 'x' in
- // an uninitialized state after this will still warn.
- //
- // TODO: Should we suppress maybe-uninitialized warnings for
- // variables initialized in this way?
- if (const Expr *E = vd->getInit()) {
- if (dr == E->IgnoreParenImpCasts())
- continue;
-
- ContainsReference CR(S.Context, dr);
- CR.Visit(const_cast<Expr*>(E));
- isSelfInit = CR.doesContainReference();
- }
- if (isSelfInit) {
- S.Diag(dr->getLocStart(),
- diag::warn_uninit_self_reference_in_init)
- << vd->getDeclName() << vd->getLocation() << dr->getSourceRange();
- } else {
- S.Diag(dr->getLocStart(), diag::warn_uninit_var)
- << vd->getDeclName() << dr->getSourceRange();
- }
- }
- else {
- S.Diag(dr->getLocStart(), diag::warn_maybe_uninit_var)
- << vd->getDeclName() << dr->getSourceRange();
- }
- }
- else {
- const BlockExpr *be = cast<BlockExpr>(vi->first);
- S.Diag(be->getLocStart(),
- isAlwaysUninit ? diag::warn_uninit_var_captured_by_block
- : diag::warn_maybe_uninit_var_captured_by_block)
- << vd->getDeclName();
- }
-
- // Report where the variable was declared when the use wasn't within
- // the initializer of that declaration.
- if (!isSelfInit)
- S.Diag(vd->getLocStart(), diag::note_uninit_var_def)
- << vd->getDeclName();
-
- // Only report the fixit once.
- if (fixitIssued)
- continue;
-
- fixitIssued = true;
-
- // Don't issue a fixit if there is already an initializer.
- if (vd->getInit())
- continue;
+ DiagnoseUninitializedUse(S, vd, vi->first, fixitIssued,
+ /*isAlwaysUninit=*/vi->second);
- // Suggest possible initialization (if any).
- const char *initialization = 0;
- QualType vdTy = vd->getType().getCanonicalType();
-
- if (vdTy->getAs<ObjCObjectPointerType>()) {
- // Check if 'nil' is defined.
- if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil")))
- initialization = " = nil";
- else
- initialization = " = 0";
- }
- else if (vdTy->isRealFloatingType())
- initialization = " = 0.0";
- else if (vdTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus)
- initialization = " = false";
- else if (vdTy->isEnumeralType())
- continue;
- else if (vdTy->isScalarType())
- initialization = " = 0";
-
- if (initialization) {
- SourceLocation loc = S.PP.getLocForEndOfToken(vd->getLocEnd());
- S.Diag(loc, diag::note_var_fixit_add_initialization)
- << FixItHint::CreateInsertion(loc, initialization);
- }
- }
delete vec;
}
delete uses;