[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