"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 :
#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"
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.
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.
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);
}
// 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}}
};
//------------------------------------------------------------------------------
#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