summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-03-27 09:46:56 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-03-27 09:46:56 +0000
commit33bf3e758d1d23eb5b8b502b86bcd681a378e3cf (patch)
treebe4b4a8f424e069c793608097f5cd1da45bc9bd7
parent28ccef788bb23d50ab17e3db6c5d0ee35a7af8d6 (diff)
downloadbcm5719-llvm-33bf3e758d1d23eb5b8b502b86bcd681a378e3cf.tar.gz
bcm5719-llvm-33bf3e758d1d23eb5b8b502b86bcd681a378e3cf.zip
Diagnose uninitialized uses of a variable within its own initializer.
This is basically the same idea as the warning on uninitialized uses of fields within an initializer list. As such, it is on by default and under -Wuninitialized. Original patch by Richard Trieu, with some massaging from me on the wording and grouping of the diagnostics. llvm-svn: 128376
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp45
-rw-r--r--clang/test/PCH/pragma-diag-section.cpp5
-rw-r--r--clang/test/PCH/pragma-diag.c3
-rw-r--r--clang/test/PCH/rdar8852495.c3
-rw-r--r--clang/test/Preprocessor/pragma_diagnostic_sections.cpp8
6 files changed, 59 insertions, 8 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 55223ac1343..6e0bec2f1fe 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -871,6 +871,9 @@ def note_uninit_reference_member : Note<
"uninitialized reference member is here">;
def warn_field_is_uninit : Warning<"field is uninitialized when used here">,
InGroup<Uninitialized>;
+def warn_uninit_self_reference_in_init : Warning<
+ "variable %0 is uninitialized when used within its own initialization">,
+ InGroup<Uninitialized>;
def warn_uninit_var : Warning<"variable %0 is possibly uninitialized when used here">,
InGroup<Uninitialized>, DefaultIgnore;
def warn_maybe_uninit_var :
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 59b4f5f2292..7a1492a53b5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/CharUnits.h"
@@ -4664,6 +4665,46 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
return true;
}
+namespace {
+ // Visits an initialization expression to see if OrigDecl is evaluated in
+ // its own initialization and throws a warning if it does.
+ class SelfReferenceChecker
+ : public EvaluatedExprVisitor<SelfReferenceChecker> {
+ Sema &S;
+ Decl *OrigDecl;
+
+ public:
+ typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited;
+
+ SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context),
+ S(S), OrigDecl(OrigDecl) { }
+
+ void VisitExpr(Expr *E) {
+ if (isa<ObjCMessageExpr>(*E)) return;
+ Inherited::VisitExpr(E);
+ }
+
+ void VisitImplicitCastExpr(ImplicitCastExpr *E) {
+ CheckForSelfReference(E);
+ Inherited::VisitImplicitCastExpr(E);
+ }
+
+ void CheckForSelfReference(ImplicitCastExpr *E) {
+ if (E->getCastKind() != CK_LValueToRValue) return;
+ Expr* SubExpr = E->getSubExpr()->IgnoreParenImpCasts();
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr);
+ if (!DRE) return;
+ Decl* ReferenceDecl = DRE->getDecl();
+ if (OrigDecl != ReferenceDecl) return;
+ LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName,
+ Sema::NotForRedeclaration);
+ S.Diag(SubExpr->getLocStart(), diag::warn_uninit_self_reference_in_init)
+ << Result.getLookupName() << OrigDecl->getLocation()
+ << SubExpr->getSourceRange();
+ }
+ };
+}
+
/// AddInitializerToDecl - Adds the initializer Init to the
/// declaration dcl. If DirectInit is true, this is C++ direct
/// initialization rather than copy initialization.
@@ -4674,6 +4715,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (RealDecl == 0 || RealDecl->isInvalidDecl())
return;
+ SelfReferenceChecker(*this, RealDecl).VisitExpr(Init);
+
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
// With declarators parsed the way they are, the parser cannot
// distinguish between a normal initializer and a pure-specifier.
@@ -5231,7 +5274,7 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (Decl *D = Group[i])
Decls.push_back(D);
- return BuildDeclaratorGroup(Decls.data(), Decls.size(),
+ return BuildDeclaratorGroup(Decls.data(), Decls.size(),
DS.getTypeSpecType() == DeclSpec::TST_auto);
}
diff --git a/clang/test/PCH/pragma-diag-section.cpp b/clang/test/PCH/pragma-diag-section.cpp
index 312f720ebd9..5b996bb2f0d 100644
--- a/clang/test/PCH/pragma-diag-section.cpp
+++ b/clang/test/PCH/pragma-diag-section.cpp
@@ -12,7 +12,10 @@
#pragma clang diagnostic ignored "-Wtautological-compare"
template <typename T>
struct TS {
- void m() { T b = b==b; }
+ void m() {
+ T a = 0;
+ T b = a==a;
+ }
};
#pragma clang diagnostic pop
diff --git a/clang/test/PCH/pragma-diag.c b/clang/test/PCH/pragma-diag.c
index c5171036400..b304c4bf8c3 100644
--- a/clang/test/PCH/pragma-diag.c
+++ b/clang/test/PCH/pragma-diag.c
@@ -13,7 +13,8 @@
#else
void f() {
- int b = b==b;
+ int a = 0;
+ int b = a==a;
}
#endif
diff --git a/clang/test/PCH/rdar8852495.c b/clang/test/PCH/rdar8852495.c
index 2d49e001b05..fb465a37ce3 100644
--- a/clang/test/PCH/rdar8852495.c
+++ b/clang/test/PCH/rdar8852495.c
@@ -16,7 +16,8 @@
#else
int f() {
- int b = b==b;
+ int a;
+ int b = a==a;
unsigned x;
signed y;
return x == y;
diff --git a/clang/test/Preprocessor/pragma_diagnostic_sections.cpp b/clang/test/Preprocessor/pragma_diagnostic_sections.cpp
index 69436b0bd84..b680fae5b99 100644
--- a/clang/test/Preprocessor/pragma_diagnostic_sections.cpp
+++ b/clang/test/Preprocessor/pragma_diagnostic_sections.cpp
@@ -2,14 +2,14 @@
// rdar://8365684
struct S {
- void m1() { int b = b==b; } // expected-warning {{always evaluates to true}}
+ void m1() { int b; while (b==b); } // expected-warning {{always evaluates to true}}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
- void m2() { int b = b==b; }
+ void m2() { int b; while (b==b); }
#pragma clang diagnostic pop
- void m3() { int b = b==b; } // expected-warning {{always evaluates to true}}
+ void m3() { int b; while (b==b); } // expected-warning {{always evaluates to true}}
};
//------------------------------------------------------------------------------
@@ -18,7 +18,7 @@ struct S {
#pragma clang diagnostic ignored "-Wtautological-compare"
template <typename T>
struct TS {
- void m() { T b = b==b; }
+ void m() { T b; while (b==b); }
};
#pragma clang diagnostic pop
OpenPOWER on IntegriCloud