[cfe-commits] r139077 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclCXX.cpp test/SemaCXX/warn-dangling-field.cpp

Chandler Carruth chandlerc at gmail.com
Fri Sep 2 19:21:57 PDT 2011


Author: chandlerc
Date: Fri Sep  2 21:21:57 2011
New Revision: 139077

URL: http://llvm.org/viewvc/llvm-project?rev=139077&view=rev
Log:
Teach -Wdangling-field to warn about temporaries bound to references as
well.

Also, clean up the flow of the code a bit, and factor things more
nicely.

Finally, add the test case that was missing from my previous
commit (sorry), with new tests added to cover temporaries and other fun
cases.

Added:
    cfe/trunk/test/SemaCXX/warn-dangling-field.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=139077&r1=139076&r2=139077&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Sep  2 21:21:57 2011
@@ -4362,6 +4362,9 @@
 def warn_init_ptr_member_to_parameter_addr : Warning<
   "initializing pointer member %0 with the stack address of parameter %1">,
   InGroup<DiagGroup<"dangling-field">>, DefaultIgnore;
+def warn_bind_ref_member_to_temporary : Warning<
+  "binding reference member %0 to a temporary value">,
+  InGroup<DiagGroup<"dangling-field">>, DefaultIgnore;
 def note_ref_or_ptr_member_declared_here : Note<
   "%select{reference|pointer}0 member declared here">;
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=139077&r1=139076&r2=139077&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Sep  2 21:21:57 2011
@@ -1500,7 +1500,6 @@
 
 /// Checks a member initializer expression for cases where reference (or
 /// pointer) members are bound to by-value parameters (or their addresses).
-/// FIXME: We should also flag temporaries here.
 static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member,
                                                Expr *Init,
                                                SourceLocation IdLoc) {
@@ -1527,22 +1526,31 @@
     }
   }
 
-  // We only warn when referring to a non-reference declaration.
-  const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParenCasts());
-  if (!DRE)
-    return;
+  if (isa<MaterializeTemporaryExpr>(Init->IgnoreParens())) {
+    // Taking the address of a temporary will be diagnosed as a hard error.
+    if (IsPointer)
+      return;
 
-  if (const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
-    if (Parameter->getType()->isReferenceType())
+    S.Diag(Init->getExprLoc(), diag::warn_bind_ref_member_to_temporary)
+      << Member << Init->getSourceRange();
+  } else if (const DeclRefExpr *DRE
+               = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
+    // We only warn when referring to a non-reference parameter declaration.
+    const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl());
+    if (!Parameter || Parameter->getType()->isReferenceType())
       return;
 
     S.Diag(Init->getExprLoc(),
            IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
                      : diag::warn_bind_ref_member_to_parameter)
       << Member << Parameter << Init->getSourceRange();
-    S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here)
-      << (unsigned)IsPointer;
+  } else {
+    // Other initializers are fine.
+    return;
   }
+
+  S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here)
+    << (unsigned)IsPointer;
 }
 
 /// Checks an initializer expression for use of uninitialized fields, such as

Added: cfe/trunk/test/SemaCXX/warn-dangling-field.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-dangling-field.cpp?rev=139077&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-dangling-field.cpp (added)
+++ cfe/trunk/test/SemaCXX/warn-dangling-field.cpp Fri Sep  2 21:21:57 2011
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fsyntax-only -Wdangling-field -verify %s
+
+struct X {
+  X(int);
+};
+struct Y {
+  operator X*();
+  operator X&();
+};
+
+struct S {
+  int &x, *y;  // expected-note {{reference member declared here}} \
+               // expected-note {{pointer member declared here}}
+  S(int i)
+    : x(i),    // expected-warning {{binding reference member 'x' to stack allocated parameter 'i'}}
+      y(&i) {} // expected-warning {{initializing pointer member 'y' with the stack address of parameter 'i'}}
+  S(int &i) : x(i), y(&i) {} // no-warning: reference parameter
+  S(int *i) : x(*i), y(i) {} // no-warning: pointer parameter
+};
+
+struct S2 {
+  const X &x; // expected-note {{reference member declared here}}
+  S2(int i) : x(i) {} // expected-warning {{binding reference member 'x' to a temporary}}
+};
+
+struct S3 {
+  X &x1, *x2;
+  S3(Y y) : x1(y), x2(y) {} // no-warning: conversion operator
+};
+
+template <typename T> struct S4 {
+  T x; // expected-note {{reference member declared here}}
+  S4(int i) : x(i) {} // expected-warning {{binding reference member 'x' to stack allocated parameter 'i'}}
+};
+
+template struct S4<int>; // no warning from this instantiation
+template struct S4<int&>; // expected-note {{in instantiation}}





More information about the cfe-commits mailing list