diff options
author | Hans Wennborg <hans@hanshq.net> | 2012-08-17 10:12:33 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2012-08-17 10:12:33 +0000 |
commit | 8be9e77f7e532866fa0ef2bc8c3cd549f0cc8da2 (patch) | |
tree | 659b0a4c7f789355f04e19029a6e6db1813756b8 | |
parent | 66a3d4754977cf0e98e510af9d68d00cbc14b7a8 (diff) |
Warn about self-initialization of references.
Initializing a reference with itself, e.g. "int &a = a;" seems like a
very bad idea.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162093 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 15 | ||||
-rw-r--r-- | test/Analysis/stack-addr-ps.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/convert-to-bool.cpp | 3 | ||||
-rw-r--r-- | test/SemaCXX/references.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/uninitialized.cpp | 19 |
5 files changed, 31 insertions, 10 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index cb3ac68852..ea181de00a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -6174,6 +6174,7 @@ namespace { Decl *OrigDecl; bool isRecordType; bool isPODType; + bool isReferenceType; public: typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited; @@ -6182,9 +6183,11 @@ namespace { S(S), OrigDecl(OrigDecl) { isPODType = false; isRecordType = false; + isReferenceType = false; if (ValueDecl *VD = dyn_cast<ValueDecl>(OrigDecl)) { isPODType = VD->getType().isPODType(S.Context); isRecordType = VD->getType()->isRecordType(); + isReferenceType = VD->getType()->isReferenceType(); } } @@ -6192,9 +6195,9 @@ namespace { // to determine which DeclRefExpr's to check. Assume that the casts // are present and continue visiting the expression. void HandleExpr(Expr *E) { - // Skip checking T a = a where T is not a record type. Doing so is a - // way to silence uninitialized warnings. - if (isRecordType) + // Skip checking T a = a where T is not a record or reference type. + // Doing so is a way to silence uninitialized warnings. + if (isRecordType || isReferenceType) if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) HandleDeclRefExpr(DRE); @@ -6309,11 +6312,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } // Check for self-references within variable initializers. - // Variables declared within a function/method body are handled - // by a dataflow analysis. + // Variables declared within a function/method body (except for references) + // are handled by a dataflow analysis. // Record types initialized by initializer list are handled here. // Initialization by constructors are handled in TryConstructorInitialization. - if (!VDecl->hasLocalStorage() && + if ((!VDecl->hasLocalStorage() || VDecl->getType()->isReferenceType()) && (isa<InitListExpr>(Init) || !VDecl->getType()->isRecordType())) CheckSelfReference(RealDecl, Init); diff --git a/test/Analysis/stack-addr-ps.cpp b/test/Analysis/stack-addr-ps.cpp index b21a03dc38..cbdb143c18 100644 --- a/test/Analysis/stack-addr-ps.cpp +++ b/test/Analysis/stack-addr-ps.cpp @@ -87,6 +87,6 @@ struct TS { // rdar://11345441 int* f5() { - int& i = i; // expected-warning {{Assigned value is garbage or undefined}} expected-note {{binding reference variable 'i' here}} + int& i = i; // expected-warning {{Assigned value is garbage or undefined}} expected-note {{binding reference variable 'i' here}} expected-warning{{variable 'i' is uninitialized when used within its own initialization}} return &i; // expected-warning {{address of stack memory associated with local variable 'i' returned}} } diff --git a/test/SemaCXX/convert-to-bool.cpp b/test/SemaCXX/convert-to-bool.cpp index c9a355549f..b52f11c93d 100644 --- a/test/SemaCXX/convert-to-bool.cpp +++ b/test/SemaCXX/convert-to-bool.cpp @@ -62,6 +62,5 @@ struct C { void test_copy_init_conversions(C c) { A &a = c; // expected-error{{no viable conversion from 'C' to 'A'}} - B &b = b; // okay + B &b = c; // okay } - diff --git a/test/SemaCXX/references.cpp b/test/SemaCXX/references.cpp index 70d3799a0e..028c690921 100644 --- a/test/SemaCXX/references.cpp +++ b/test/SemaCXX/references.cpp @@ -136,4 +136,4 @@ namespace PR8608 { } // The following crashed trying to recursively evaluate the LValue. -const int &do_not_crash = do_not_crash; +const int &do_not_crash = do_not_crash; // expected-warning{{variable 'do_not_crash' is uninitialized when used within its own initialization}} diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index 890f212930..385548b51c 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -378,3 +378,22 @@ namespace statics { } } } + +namespace references { + int &a = a; // expected-warning{{variable 'a' is uninitialized when used within its own initialization}} + + struct S { + S() : a(a) {} // expected-warning{{field is uninitialized when used here}} + int &a; + }; + + void f() { + int &a = a; // expected-warning{{variable 'a' is uninitialized when used within its own initialization}} + } + + struct T { + T() : a(b), b(a) {} // FIXME: Warn here. + int &a, &b; + int &c = c; // FIXME: Warn here. + }; +} |