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

Andrew Trick atrick at apple.com
Fri Sep 2 09:21:39 PDT 2011


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.

-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




More information about the cfe-commits mailing list