[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