summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-06-21 17:03:29 +0000
committerDouglas Gregor <dgregor@apple.com>2011-06-21 17:03:29 +0000
commitfe31481f6829eaebf40205a1695a7aa68f0de36c (patch)
tree8e11d0bc889e40a78f28888e622ac4b19dfc4d7a /clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
parentfc4ccb20c6024606f23463988b3b21ab4288e653 (diff)
downloadbcm5719-llvm-fe31481f6829eaebf40205a1695a7aa68f0de36c.tar.gz
bcm5719-llvm-fe31481f6829eaebf40205a1695a7aa68f0de36c.zip
Introduce a new AST node describing reference binding to temporaries.
MaterializeTemporaryExpr captures a reference binding to a temporary value, making explicit that the temporary value (a prvalue) needs to be materialized into memory so that its address can be used. The intended AST invariant here is that a reference will always bind to a glvalue, and MaterializeTemporaryExpr will be used to convert prvalues into glvalues for that binding to happen. For example, given const int& r = 1.0; The initializer of "r" will be a MaterializeTemporaryExpr whose subexpression is an implicit conversion from the double literal "1.0" to an integer value. IR generation benefits most from this new node, since it was previously guessing (badly) when to materialize temporaries for the purposes of reference binding. There are likely more refactoring and cleanups we could perform there, but the introduction of MaterializeTemporaryExpr fixes PR9565, a case where IR generation would effectively bind a const reference directly to a bitfield in a struct. Addresses <rdar://problem/9552231>. llvm-svn: 133521
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp27
1 files changed, 19 insertions, 8 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
index e4e5f54770b..de6da4f8c37 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
@@ -237,8 +237,11 @@ const GRState *IteratorsChecker::invalidateIterators(const GRState *state,
const GRState *IteratorsChecker::handleAssign(const GRState *state,
const Expr *lexp, const Expr *rexp, const LocationContext *LC) const {
// Skip the cast if present.
- if (isa<ImplicitCastExpr>(lexp))
- lexp = dyn_cast<ImplicitCastExpr>(lexp)->getSubExpr();
+ if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(lexp))
+ lexp = M->GetTemporaryExpr();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(lexp))
+ lexp = ICE->getSubExpr();
SVal sv = state->getSVal(lexp);
const MemRegion *MR = sv.getAsRegion();
if (!MR)
@@ -260,8 +263,11 @@ const GRState *IteratorsChecker::handleAssign(const GRState *state,
const MemRegion *MR, const Expr *rexp, const LocationContext *LC) const {
// Assume unknown until we find something definite.
state = state->set<IteratorState>(MR, RefState::getUnknown());
- if (isa<ImplicitCastExpr>(rexp))
- rexp = dyn_cast<ImplicitCastExpr>(rexp)->getSubExpr();
+ if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(rexp))
+ rexp = M->GetTemporaryExpr();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(rexp))
+ rexp = ICE->getSubExpr();
// Need to handle three cases: MemberCall, copy, copy with addition.
if (const CallExpr *CE = dyn_cast<CallExpr>(rexp)) {
// Handle MemberCall.
@@ -347,8 +353,10 @@ const DeclRefExpr *IteratorsChecker::getDeclRefExpr(const Expr *E) const {
E = CE->getArg(0);
}
}
- if (isa<ImplicitCastExpr>(E))
- E = dyn_cast<ImplicitCastExpr>(E)->getSubExpr();
+ if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = M->GetTemporaryExpr();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+ E = ICE->getSubExpr();
// If it isn't one of our types, don't do anything.
if (getTemplateKind(E->getType()) != VectorIteratorKind)
return NULL;
@@ -520,8 +528,11 @@ void IteratorsChecker::checkPreStmt(const DeclStmt *DS,
if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitEx)) {
if (CE->getNumArgs() == 1) {
const Expr *E = CE->getArg(0);
- if (isa<ImplicitCastExpr>(E))
- InitEx = dyn_cast<ImplicitCastExpr>(E)->getSubExpr();
+ if (const MaterializeTemporaryExpr *M
+ = dyn_cast<MaterializeTemporaryExpr>(E))
+ E = M->GetTemporaryExpr();
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+ InitEx = ICE->getSubExpr();
state = handleAssign(state, MR, InitEx,
C.getPredecessor()->getLocationContext());
}
OpenPOWER on IntegriCloud