From 621ba4f0dba0accdf67fb38e98bbe14db22ddf8e Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 15 Nov 2012 08:19:20 +0000 Subject: [PATCH] Teach the uninitialized field warning about anonymous structs and union members. Fixes PR14073! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168031 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclCXX.cpp | 32 +++++++++++++++++------- test/SemaCXX/constructor-initializer.cpp | 6 +++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 2c760f4930..a8ddc51f3f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1795,7 +1795,11 @@ namespace { public: typedef EvaluatedExprVisitor Inherited; UninitializedFieldVisitor(Sema &S, ValueDecl *VD) : Inherited(S.Context), - S(S), VD(VD) { + S(S) { + if (IndirectFieldDecl *IFD = dyn_cast(VD)) + this->VD = IFD->getAnonField(); + else + this->VD = VD; } void HandleExpr(Expr *E) { @@ -1812,23 +1816,33 @@ namespace { if (MemberExpr *ME = dyn_cast(E)) { if (isa(ME->getMemberDecl())) - return; + return; + + // FieldME is the inner-most MemberExpr that is not an anonymous struct + // or union. + MemberExpr *FieldME = ME; + Expr *Base = E; while (isa(Base)) { - ME = dyn_cast(Base); - if (VarDecl *VarD = dyn_cast(ME->getMemberDecl())) - if (VarD->hasGlobalStorage()) - return; + ME = cast(Base); + + if (isa(ME->getMemberDecl())) + return; + + if (FieldDecl *FD = dyn_cast(ME->getMemberDecl())) + if (!FD->isAnonymousStructOrUnion()) + FieldME = ME; + Base = ME->getBase(); } - if (VD == ME->getMemberDecl() && isa(Base)) { + if (VD == FieldME->getMemberDecl() && isa(Base)) { unsigned diag = VD->getType()->isReferenceType() ? diag::warn_reference_field_is_uninit : diag::warn_field_is_uninit; - S.Diag(ME->getExprLoc(), diag) << ME->getMemberNameInfo().getName(); - return; + S.Diag(FieldME->getExprLoc(), diag) << VD; } + return; } if (ConditionalOperator *CO = dyn_cast(E)) { diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp index ecbe7bf5b9..c54956db41 100644 --- a/test/SemaCXX/constructor-initializer.cpp +++ b/test/SemaCXX/constructor-initializer.cpp @@ -283,3 +283,9 @@ namespace PR12049 { int member; // expected-error {{expected ')'}} }; } + +namespace PR14073 { + struct S1 { union { int n; }; S1() : n(n) {} }; // expected-warning {{field 'n' is uninitialized when used here}} + struct S2 { union { union { int n; }; char c; }; S2() : n(n) {} }; // expected-warning {{field 'n' is uninitialized when used here}} + struct S3 { struct { int n; }; S3() : n(n) {} }; // expected-warning {{field 'n' is uninitialized when used here}} +}