[cfe-commits] r138969 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaInit.cpp test/SemaCXX/uninitialized.cpp

Chandler Carruth chandlerc at google.com
Fri Sep 2 09:39:44 PDT 2011


On Fri, Sep 2, 2011 at 9:21 AM, Andrew Trick <atrick at apple.com> wrote:

> Hi Richard,
>
> We're hitting a new DejaGNU failure that I'm guessing is caused by this
> checkin:
> g++.old-deja/g++.brendan/parse6.C
>
> I haven't seen how it fails yet, just hoping someone can fix or revert
> before I get around to it.
>

FYI, I'm not in the office yet but Richard or I should be able to look at
this today and fix it. Just so you don't stress / spend too much time on it.
=D


>
> -Andy
>
> On Sep 1, 2011, at 2:44 PM, Richard Trieu wrote:
>
> > Author: rtrieu
> > Date: Thu Sep  1 16:44:13 2011
> > New Revision: 138969
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=138969&view=rev
> > Log:
> > Extend the self-reference warning to catch when a constructor references
> itself upon initialization, such as using itself within its own copy
> constructor.
> >
> > struct S {};
> > S s(s);
> >
> > Modified:
> >    cfe/trunk/include/clang/Sema/Sema.h
> >    cfe/trunk/lib/Sema/SemaDecl.cpp
> >    cfe/trunk/lib/Sema/SemaInit.cpp
> >    cfe/trunk/test/SemaCXX/uninitialized.cpp
> >
> > Modified: cfe/trunk/include/clang/Sema/Sema.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=138969&r1=138968&r2=138969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Sema/Sema.h (original)
> > +++ cfe/trunk/include/clang/Sema/Sema.h Thu Sep  1 16:44:13 2011
> > @@ -1035,6 +1035,7 @@
> >   bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
> >                                SourceLocation EqualLoc);
> >
> > +  void CheckSelfReference(Decl *OrigDecl, Expr *E);
> >   void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit,
> >                             bool TypeMayContainAuto);
> >   void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto);
> >
> > Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=138969&r1=138968&r2=138969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep  1 16:44:13 2011
> > @@ -5407,41 +5407,88 @@
> >       : public EvaluatedExprVisitor<SelfReferenceChecker> {
> >     Sema &S;
> >     Decl *OrigDecl;
> > +    bool isRecordType;
> > +    bool isPODType;
> >
> >   public:
> >     typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited;
> >
> >     SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context),
> > -                                                    S(S),
> OrigDecl(OrigDecl) { }
> > +                                                    S(S),
> OrigDecl(OrigDecl) {
> > +      isPODType = false;
> > +      isRecordType = false;
> > +      if (ValueDecl *VD = dyn_cast<ValueDecl>(OrigDecl)) {
> > +        isPODType = VD->getType().isPODType(S.Context);
> > +        isRecordType = VD->getType()->isRecordType();
> > +      }
> > +    }
> >
> >     void VisitExpr(Expr *E) {
> >       if (isa<ObjCMessageExpr>(*E)) return;
> > +      if (isRecordType) {
> > +        Expr *expr = E;
> > +        if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
> > +          ValueDecl *VD = ME->getMemberDecl();
> > +          if (isa<EnumConstantDecl>(VD) || isa<VarDecl>(VD)) return;
> > +          expr = ME->getBase();
> > +        }
> > +        if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(expr)) {
> > +          HandleDeclRefExpr(DRE);
> > +          return;
> > +        }
> > +      }
> >       Inherited::VisitExpr(E);
> >     }
> >
> > +    void VisitMemberExpr(MemberExpr *E) {
> > +      if (isa<FieldDecl>(E->getMemberDecl()))
> > +        if (DeclRefExpr *DRE
> > +              =
> dyn_cast<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts())) {
> > +          HandleDeclRefExpr(DRE);
> > +          return;
> > +        }
> > +      Inherited::VisitMemberExpr(E);
> > +    }
> > +
> >     void VisitImplicitCastExpr(ImplicitCastExpr *E) {
> > -      CheckForSelfReference(E);
> > +      if ((!isRecordType &&E->getCastKind() == CK_LValueToRValue) ||
> > +          (isRecordType && E->getCastKind() == CK_NoOp)) {
> > +        Expr* SubExpr = E->getSubExpr()->IgnoreParenImpCasts();
> > +        if (MemberExpr *ME = dyn_cast<MemberExpr>(SubExpr))
> > +          SubExpr = ME->getBase()->IgnoreParenImpCasts();
> > +        if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
> > +          HandleDeclRefExpr(DRE);
> > +          return;
> > +        }
> > +      }
> >       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();
> > +    void VisitUnaryOperator(UnaryOperator *E) {
> > +      // For POD record types, addresses of its own members are
> well-defined.
> > +      if (isRecordType && isPODType) return;
> > +      Inherited::VisitUnaryOperator(E);
> > +    }
> > +
> > +    void HandleDeclRefExpr(DeclRefExpr *DRE) {
> > +      Decl* ReferenceDecl = DRE->getDecl();
> >       if (OrigDecl != ReferenceDecl) return;
> >       LookupResult Result(S, DRE->getNameInfo(),
> Sema::LookupOrdinaryName,
> >                           Sema::NotForRedeclaration);
> > -      S.DiagRuntimeBehavior(SubExpr->getLocStart(), SubExpr,
> > +      S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
> >
> S.PDiag(diag::warn_uninit_self_reference_in_init)
> > -                              << Result.getLookupName()
> > +                              << Result.getLookupName()
> >                               << OrigDecl->getLocation()
> > -                              << SubExpr->getSourceRange());
> > +                              << DRE->getSourceRange());
> >     }
> >   };
> > }
> >
> > +/// CheckSelfReference - Warns if OrigDecl is used in expression E.
> > +void Sema::CheckSelfReference(Decl* OrigDecl, Expr *E) {
> > +  SelfReferenceChecker(*this, OrigDecl).VisitExpr(E);
> > +}
> > +
> > /// AddInitializerToDecl - Adds the initializer Init to the
> > /// declaration dcl. If DirectInit is true, this is C++ direct
> > /// initialization rather than copy initialization.
> > @@ -5457,10 +5504,10 @@
> >     // Variables declared within a function/method body are handled
> >     // by a dataflow analysis.
> >     if (!vd->hasLocalStorage() && !vd->isStaticLocal())
> > -      SelfReferenceChecker(*this, RealDecl).VisitExpr(Init);
> > +      CheckSelfReference(RealDecl, Init);
> >   }
> >   else {
> > -    SelfReferenceChecker(*this, RealDecl).VisitExpr(Init);
> > +    CheckSelfReference(RealDecl, Init);
> >   }
> >
> >   if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
> >
> > Modified: cfe/trunk/lib/Sema/SemaInit.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=138969&r1=138968&r2=138969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Sep  1 16:44:13 2011
> > @@ -3078,6 +3078,14 @@
> >                                          Expr **Args, unsigned NumArgs,
> >                                          QualType DestType,
> >                                          InitializationSequence
> &Sequence) {
> > +  // Check constructor arguments for self reference.
> > +  if (DeclaratorDecl *DD = Entity.getDecl())
> > +    // Parameters arguments are occassionially constructed with itself,
> > +    // for instance, in recursive functions.  Skip them.
> > +    if (!isa<ParmVarDecl>(DD))
> > +      for (unsigned i = 0; i < NumArgs; ++i)
> > +        S.CheckSelfReference(DD, Args[i]);
> > +
> >   // Build the candidate set directly in the initialization sequence
> >   // structure, so that it will persist if we fail.
> >   OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
> >
> > Modified: cfe/trunk/test/SemaCXX/uninitialized.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/uninitialized.cpp?rev=138969&r1=138968&r2=138969&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/SemaCXX/uninitialized.cpp (original)
> > +++ cfe/trunk/test/SemaCXX/uninitialized.cpp Thu Sep  1 16:44:13 2011
> > @@ -24,6 +24,78 @@
> > int j = far(j);
> > int k = __alignof__(k);
> >
> > +
> > +// Test self-references with record types.
> > +class A {
> > +  // Non-POD class.
> > +  public:
> > +    enum count { ONE, TWO, THREE };
> > +    int num;
> > +    static int count;
> > +    int get() const { return num; }
> > +    void set(int x) { num = x; }
> > +    static int zero() { return 0; }
> > +
> > +    A() {}
> > +    A(A const &a) {}
> > +    A(int x) {}
> > +    A(int *x) {}
> > +    A(A *a) {}
> > +};
> > +
> > +A getA() { return A(); }
> > +A getA(int x) { return A(); }
> > +A getA(A* a) { return A(); }
> > +
> > +void setupA() {
> > +  A a1;
> > +  a1.set(a1.get());
> > +  A a2(a1.get());
> > +  A a3(a1);
> > +  A a4(&a4);
> > +  A a5(a5.zero());
> > +  A a6(a6.ONE);
> > +  A a7 = getA();
> > +  A a8 = getA(a8.TWO);
> > +  A a9 = getA(&a9);
> > +  A a10(a10.count);
> > +
> > +  A a11(a11);  // expected-warning {{variable 'a11' is uninitialized
> when used within its own initialization}}
> > +  A a12(a12.get());  // expected-warning {{variable 'a12' is
> uninitialized when used within its own initialization}}
> > +  A a13(a13.num);  // expected-warning {{variable 'a13' is uninitialized
> when used within its own initialization}}
> > +  A a14 = A(a14);  // expected-warning {{variable 'a14' is uninitialized
> when used within its own initialization}}
> > +  A a15 = getA(a15.num);  // expected-warning {{variable 'a15' is
> uninitialized when used within its own initialization}}
> > +  A a16(&a16.num);  // expected-warning {{variable 'a16' is
> uninitialized when used within its own initialization}}
> > +}
> > +
> > +struct B {
> > +  // POD struct.
> > +  int x;
> > +  int *y;
> > +};
> > +
> > +B getB() { return B(); };
> > +B getB(int x) { return B(); };
> > +B getB(int *x) { return B(); };
> > +B getB(B *b) { return B(); };
> > +
> > +void setupB() {
> > +  B b1;
> > +  B b2(b1);
> > +  B b3 = { 5, &b3.x };
> > +  B b4 = getB();
> > +  B b5 = getB(&b5);
> > +  B b6 = getB(&b6.x);
> > +
> > +  // Silence unused warning
> > +  (void) b2;
> > +  (void) b4;
> > +
> > +  B b7(b7);  // expected-warning {{variable 'b7' is uninitialized when
> used within its own initialization}}
> > +  B b8 = getB(b8.x);  // expected-warning {{variable 'b8' is
> uninitialized when used within its own initialization}}
> > +  B b9 = getB(b9.y);  // expected-warning {{variable 'b9' is
> uninitialized when used within its own initialization}}
> > +}
> > +
> > // Also test similar constructs in a field's initializer.
> > struct S {
> >   int x;
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20110902/d8974cac/attachment.html>


More information about the cfe-commits mailing list