From 33bf3e758d1d23eb5b8b502b86bcd681a378e3cf Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sun, 27 Mar 2011 09:46:56 +0000 Subject: 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 --- clang/lib/Sema/SemaDecl.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'clang/lib/Sema/SemaDecl.cpp') 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 { + Sema &S; + Decl *OrigDecl; + + public: + typedef EvaluatedExprVisitor Inherited; + + SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context), + S(S), OrigDecl(OrigDecl) { } + + void VisitExpr(Expr *E) { + if (isa(*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(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(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); } -- cgit v1.2.3