summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-09-03 02:21:57 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-09-03 02:21:57 +0000
commitd551d4e1dae50b4d8a613d62afdafba3ecbd8cc8 (patch)
tree2ee1b12bf9af3d4531ea76b898ee5776f9cd0cd2 /clang/lib
parent7c1d6358a2f2eac2a5e73580fe63cf3c879d9273 (diff)
downloadbcm5719-llvm-d551d4e1dae50b4d8a613d62afdafba3ecbd8cc8.tar.gz
bcm5719-llvm-d551d4e1dae50b4d8a613d62afdafba3ecbd8cc8.zip
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. llvm-svn: 139077
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp26
1 files changed, 17 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 14890cf920e..f35fdeda38c 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1500,7 +1500,6 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
/// 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 @@ static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member,
}
}
- // 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
OpenPOWER on IntegriCloud