blob: 4f2810ea94ef188e8d1b5f0af3012b40e1eb6748 [file] [log] [blame]
Tom Caredb2fa8a2010-07-06 21:43:29 +00001//==- IdempotentOperationChecker.cpp - Idempotent Operations ----*- C++ -*-==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a set of path-sensitive checks for idempotent and/or
11// tautological operations. Each potential operation is checked along all paths
12// to see if every path results in a pointless operation.
13// +-------------------------------------------+
14// |Table of idempotent/tautological operations|
15// +-------------------------------------------+
16//+--------------------------------------------------------------------------+
17//|Operator | x op x | x op 1 | 1 op x | x op 0 | 0 op x | x op ~0 | ~0 op x |
18//+--------------------------------------------------------------------------+
19// +, += | | | | x | x | |
20// -, -= | | | | x | -x | |
21// *, *= | | x | x | 0 | 0 | |
22// /, /= | 1 | x | | N/A | 0 | |
23// &, &= | x | | | 0 | 0 | x | x
24// |, |= | x | | | x | x | ~0 | ~0
25// ^, ^= | 0 | | | x | x | |
26// <<, <<= | | | | x | 0 | |
27// >>, >>= | | | | x | 0 | |
28// || | 1 | 1 | 1 | x | x | 1 | 1
29// && | 1 | x | x | 0 | 0 | x | x
30// = | x | | | | | |
31// == | 1 | | | | | |
32// >= | 1 | | | | | |
33// <= | 1 | | | | | |
34// > | 0 | | | | | |
35// < | 0 | | | | | |
36// != | 0 | | | | | |
37//===----------------------------------------------------------------------===//
38//
Tom Carea7a8a452010-08-12 22:45:47 +000039// Things TODO:
Tom Caredb2fa8a2010-07-06 21:43:29 +000040// - Improved error messages
41// - Handle mixed assumptions (which assumptions can belong together?)
42// - Finer grained false positive control (levels)
Tom Carea7a8a452010-08-12 22:45:47 +000043// - Handling ~0 values
Tom Caredb2fa8a2010-07-06 21:43:29 +000044
Tom Care1fafd1d2010-08-06 22:23:07 +000045#include "GRExprEngineExperimentalChecks.h"
Tom Carea7a8a452010-08-12 22:45:47 +000046#include "clang/Analysis/CFGStmtMap.h"
Tom Caredb2fa8a2010-07-06 21:43:29 +000047#include "clang/Checker/BugReporter/BugType.h"
Tom Carea9fbf5b2010-07-27 23:26:07 +000048#include "clang/Checker/PathSensitive/CheckerHelpers.h"
Tom Caredb2fa8a2010-07-06 21:43:29 +000049#include "clang/Checker/PathSensitive/CheckerVisitor.h"
Tom Carea7a8a452010-08-12 22:45:47 +000050#include "clang/Checker/PathSensitive/GRCoreEngine.h"
Tom Caredb2fa8a2010-07-06 21:43:29 +000051#include "clang/Checker/PathSensitive/SVals.h"
52#include "clang/AST/Stmt.h"
53#include "llvm/ADT/DenseMap.h"
Tom Carea7a8a452010-08-12 22:45:47 +000054#include "llvm/ADT/SmallSet.h"
Chandler Carruth256565b2010-07-07 00:07:37 +000055#include "llvm/Support/ErrorHandling.h"
Tom Carea7a8a452010-08-12 22:45:47 +000056#include <deque>
Tom Caredb2fa8a2010-07-06 21:43:29 +000057
58using namespace clang;
59
60namespace {
61class IdempotentOperationChecker
62 : public CheckerVisitor<IdempotentOperationChecker> {
63 public:
64 static void *getTag();
65 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
Tom Carebc42c532010-08-03 01:55:07 +000066 void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, GRExprEngine &Eng);
Tom Caredb2fa8a2010-07-06 21:43:29 +000067
68 private:
69 // Our assumption about a particular operation.
Ted Kremenekfe97fa12010-08-02 20:33:02 +000070 enum Assumption { Possible = 0, Impossible, Equal, LHSis1, RHSis1, LHSis0,
Tom Caredb2fa8a2010-07-06 21:43:29 +000071 RHSis0 };
72
73 void UpdateAssumption(Assumption &A, const Assumption &New);
74
75 /// contains* - Useful recursive methods to see if a statement contains an
76 /// element somewhere. Used in static analysis to reduce false positives.
Tom Caredf4ca422010-07-16 20:41:41 +000077 static bool isParameterSelfAssign(const Expr *LHS, const Expr *RHS);
78 static bool isTruncationExtensionAssignment(const Expr *LHS,
79 const Expr *RHS);
Tom Carea7a8a452010-08-12 22:45:47 +000080 static bool PathWasCompletelyAnalyzed(const CFG *C,
81 const CFGBlock *CB,
82 const GRCoreEngine &CE);
83 static bool CanVary(const Expr *Ex, ASTContext &Ctx);
Tom Care50e8ac22010-08-16 21:43:52 +000084 static bool isPseudoConstant(const DeclRefExpr *D);
Tom Caredb2fa8a2010-07-06 21:43:29 +000085
86 // Hash table
Tom Carea7a8a452010-08-12 22:45:47 +000087 typedef llvm::DenseMap<const BinaryOperator *,
88 std::pair<Assumption, AnalysisContext*> >
89 AssumptionMap;
Tom Caredb2fa8a2010-07-06 21:43:29 +000090 AssumptionMap hash;
91};
92}
93
94void *IdempotentOperationChecker::getTag() {
95 static int x = 0;
96 return &x;
97}
98
99void clang::RegisterIdempotentOperationChecker(GRExprEngine &Eng) {
100 Eng.registerCheck(new IdempotentOperationChecker());
101}
102
103void IdempotentOperationChecker::PreVisitBinaryOperator(
104 CheckerContext &C,
105 const BinaryOperator *B) {
Ted Kremenekfe97fa12010-08-02 20:33:02 +0000106 // Find or create an entry in the hash for this BinaryOperator instance.
107 // If we haven't done a lookup before, it will get default initialized to
108 // 'Possible'.
Tom Carea7a8a452010-08-12 22:45:47 +0000109 std::pair<Assumption, AnalysisContext *> &Data = hash[B];
110 Assumption &A = Data.first;
111 Data.second = C.getCurrentAnalysisContext();
Tom Caredb2fa8a2010-07-06 21:43:29 +0000112
113 // If we already have visited this node on a path that does not contain an
114 // idempotent operation, return immediately.
115 if (A == Impossible)
116 return;
117
Tom Carea7a8a452010-08-12 22:45:47 +0000118 // Retrieve both sides of the operator and determine if they can vary (which
119 // may mean this is a false positive.
Tom Caredb2fa8a2010-07-06 21:43:29 +0000120 const Expr *LHS = B->getLHS();
121 const Expr *RHS = B->getRHS();
Tom Carea7a8a452010-08-12 22:45:47 +0000122 bool LHSCanVary = CanVary(LHS, C.getASTContext());
123 bool RHSCanVary = CanVary(RHS, C.getASTContext());
Tom Caredb2fa8a2010-07-06 21:43:29 +0000124
125 const GRState *state = C.getState();
126
127 SVal LHSVal = state->getSVal(LHS);
128 SVal RHSVal = state->getSVal(RHS);
129
130 // If either value is unknown, we can't be 100% sure of all paths.
131 if (LHSVal.isUnknownOrUndef() || RHSVal.isUnknownOrUndef()) {
132 A = Impossible;
133 return;
134 }
135 BinaryOperator::Opcode Op = B->getOpcode();
136
137 // Dereference the LHS SVal if this is an assign operation
138 switch (Op) {
139 default:
140 break;
141
142 // Fall through intentional
143 case BinaryOperator::AddAssign:
144 case BinaryOperator::SubAssign:
145 case BinaryOperator::MulAssign:
146 case BinaryOperator::DivAssign:
147 case BinaryOperator::AndAssign:
148 case BinaryOperator::OrAssign:
149 case BinaryOperator::XorAssign:
150 case BinaryOperator::ShlAssign:
151 case BinaryOperator::ShrAssign:
152 case BinaryOperator::Assign:
153 // Assign statements have one extra level of indirection
154 if (!isa<Loc>(LHSVal)) {
155 A = Impossible;
156 return;
157 }
158 LHSVal = state->getSVal(cast<Loc>(LHSVal));
159 }
160
161
162 // We now check for various cases which result in an idempotent operation.
163
164 // x op x
165 switch (Op) {
166 default:
167 break; // We don't care about any other operators.
168
169 // Fall through intentional
Tom Caredf4ca422010-07-16 20:41:41 +0000170 case BinaryOperator::Assign:
171 // x Assign x has a few more false positives we can check for
172 if (isParameterSelfAssign(RHS, LHS)
173 || isTruncationExtensionAssignment(RHS, LHS)) {
174 A = Impossible;
175 return;
176 }
177
Tom Caredb2fa8a2010-07-06 21:43:29 +0000178 case BinaryOperator::SubAssign:
179 case BinaryOperator::DivAssign:
180 case BinaryOperator::AndAssign:
181 case BinaryOperator::OrAssign:
182 case BinaryOperator::XorAssign:
Tom Caredb2fa8a2010-07-06 21:43:29 +0000183 case BinaryOperator::Sub:
184 case BinaryOperator::Div:
185 case BinaryOperator::And:
186 case BinaryOperator::Or:
187 case BinaryOperator::Xor:
188 case BinaryOperator::LOr:
189 case BinaryOperator::LAnd:
Tom Carea7a8a452010-08-12 22:45:47 +0000190 if (LHSVal != RHSVal || !LHSCanVary || !RHSCanVary)
Tom Caredb2fa8a2010-07-06 21:43:29 +0000191 break;
192 UpdateAssumption(A, Equal);
193 return;
194 }
195
196 // x op 1
197 switch (Op) {
198 default:
199 break; // We don't care about any other operators.
200
201 // Fall through intentional
202 case BinaryOperator::MulAssign:
203 case BinaryOperator::DivAssign:
204 case BinaryOperator::Mul:
205 case BinaryOperator::Div:
206 case BinaryOperator::LOr:
207 case BinaryOperator::LAnd:
Tom Carea7a8a452010-08-12 22:45:47 +0000208 if (!RHSVal.isConstant(1) || !RHSCanVary)
Tom Caredb2fa8a2010-07-06 21:43:29 +0000209 break;
210 UpdateAssumption(A, RHSis1);
211 return;
212 }
213
214 // 1 op x
215 switch (Op) {
216 default:
217 break; // We don't care about any other operators.
218
219 // Fall through intentional
220 case BinaryOperator::MulAssign:
221 case BinaryOperator::Mul:
222 case BinaryOperator::LOr:
223 case BinaryOperator::LAnd:
Tom Carea7a8a452010-08-12 22:45:47 +0000224 if (!LHSVal.isConstant(1) || !LHSCanVary)
Tom Caredb2fa8a2010-07-06 21:43:29 +0000225 break;
226 UpdateAssumption(A, LHSis1);
227 return;
228 }
229
230 // x op 0
231 switch (Op) {
232 default:
233 break; // We don't care about any other operators.
234
235 // Fall through intentional
236 case BinaryOperator::AddAssign:
237 case BinaryOperator::SubAssign:
238 case BinaryOperator::MulAssign:
239 case BinaryOperator::AndAssign:
240 case BinaryOperator::OrAssign:
241 case BinaryOperator::XorAssign:
242 case BinaryOperator::Add:
243 case BinaryOperator::Sub:
244 case BinaryOperator::Mul:
245 case BinaryOperator::And:
246 case BinaryOperator::Or:
247 case BinaryOperator::Xor:
248 case BinaryOperator::Shl:
249 case BinaryOperator::Shr:
250 case BinaryOperator::LOr:
251 case BinaryOperator::LAnd:
Tom Carea7a8a452010-08-12 22:45:47 +0000252 if (!RHSVal.isConstant(0) || !RHSCanVary)
Tom Caredb2fa8a2010-07-06 21:43:29 +0000253 break;
254 UpdateAssumption(A, RHSis0);
255 return;
256 }
257
258 // 0 op x
259 switch (Op) {
260 default:
261 break; // We don't care about any other operators.
262
263 // Fall through intentional
264 //case BinaryOperator::AddAssign: // Common false positive
265 case BinaryOperator::SubAssign: // Check only if unsigned
266 case BinaryOperator::MulAssign:
267 case BinaryOperator::DivAssign:
268 case BinaryOperator::AndAssign:
269 //case BinaryOperator::OrAssign: // Common false positive
270 //case BinaryOperator::XorAssign: // Common false positive
271 case BinaryOperator::ShlAssign:
272 case BinaryOperator::ShrAssign:
273 case BinaryOperator::Add:
274 case BinaryOperator::Sub:
275 case BinaryOperator::Mul:
276 case BinaryOperator::Div:
277 case BinaryOperator::And:
278 case BinaryOperator::Or:
279 case BinaryOperator::Xor:
280 case BinaryOperator::Shl:
281 case BinaryOperator::Shr:
282 case BinaryOperator::LOr:
283 case BinaryOperator::LAnd:
Tom Carea7a8a452010-08-12 22:45:47 +0000284 if (!LHSVal.isConstant(0) || !LHSCanVary)
Tom Caredb2fa8a2010-07-06 21:43:29 +0000285 break;
286 UpdateAssumption(A, LHSis0);
287 return;
288 }
289
290 // If we get to this point, there has been a valid use of this operation.
291 A = Impossible;
292}
293
294void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
Ted Kremenek3e5637f2010-07-27 18:49:08 +0000295 BugReporter &BR,
Tom Carebc42c532010-08-03 01:55:07 +0000296 GRExprEngine &Eng) {
Tom Caredb2fa8a2010-07-06 21:43:29 +0000297 // Iterate over the hash to see if we have any paths with definite
298 // idempotent operations.
Tom Carea7a8a452010-08-12 22:45:47 +0000299 for (AssumptionMap::const_iterator i = hash.begin(); i != hash.end(); ++i) {
300 // Unpack the hash contents
301 const std::pair<Assumption, AnalysisContext *> &Data = i->second;
302 const Assumption &A = Data.first;
303 AnalysisContext *AC = Data.second;
Ted Kremenek3e5637f2010-07-27 18:49:08 +0000304
Tom Carea7a8a452010-08-12 22:45:47 +0000305 const BinaryOperator *B = i->first;
Tom Caredb2fa8a2010-07-06 21:43:29 +0000306
Tom Carea7a8a452010-08-12 22:45:47 +0000307 if (A == Impossible)
308 continue;
309
310 // If the analyzer did not finish, check to see if we can still emit this
311 // warning
312 if (Eng.hasWorkRemaining()) {
313 const CFGStmtMap *CBM = CFGStmtMap::Build(AC->getCFG(),
314 &AC->getParentMap());
315
316 // If we can trace back
317 if (!PathWasCompletelyAnalyzed(AC->getCFG(),
318 CBM->getBlock(B),
319 Eng.getCoreEngine()))
320 continue;
321
322 delete CBM;
Tom Caredb2fa8a2010-07-06 21:43:29 +0000323 }
Tom Carea7a8a452010-08-12 22:45:47 +0000324
325 // Select the error message.
326 llvm::SmallString<128> buf;
327 llvm::raw_svector_ostream os(buf);
328 switch (A) {
329 case Equal:
330 if (B->getOpcode() == BinaryOperator::Assign)
331 os << "Assigned value is always the same as the existing value";
332 else
333 os << "Both operands to '" << B->getOpcodeStr()
334 << "' always have the same value";
335 break;
336 case LHSis1:
337 os << "The left operand to '" << B->getOpcodeStr() << "' is always 1";
338 break;
339 case RHSis1:
340 os << "The right operand to '" << B->getOpcodeStr() << "' is always 1";
341 break;
342 case LHSis0:
343 os << "The left operand to '" << B->getOpcodeStr() << "' is always 0";
344 break;
345 case RHSis0:
346 os << "The right operand to '" << B->getOpcodeStr() << "' is always 0";
347 break;
348 case Possible:
349 llvm_unreachable("Operation was never marked with an assumption");
350 case Impossible:
351 llvm_unreachable(0);
352 }
353
354 // Create the SourceRange Arrays
355 SourceRange S[2] = { i->first->getLHS()->getSourceRange(),
356 i->first->getRHS()->getSourceRange() };
357 BR.EmitBasicReport("Idempotent operation", "Dead code",
358 os.str(), i->first->getOperatorLoc(), S, 2);
Tom Caredb2fa8a2010-07-06 21:43:29 +0000359 }
360}
361
362// Updates the current assumption given the new assumption
363inline void IdempotentOperationChecker::UpdateAssumption(Assumption &A,
364 const Assumption &New) {
365 switch (A) {
366 // If we don't currently have an assumption, set it
367 case Possible:
368 A = New;
369 return;
370
371 // If we have determined that a valid state happened, ignore the new
372 // assumption.
373 case Impossible:
374 return;
375
376 // Any other case means that we had a different assumption last time. We don't
377 // currently support mixing assumptions for diagnostic reasons, so we set
378 // our assumption to be impossible.
379 default:
380 A = Impossible;
381 return;
382 }
383}
384
Tom Caredf4ca422010-07-16 20:41:41 +0000385// Check for a statement were a parameter is self assigned (to avoid an unused
386// variable warning)
387bool IdempotentOperationChecker::isParameterSelfAssign(const Expr *LHS,
388 const Expr *RHS) {
389 LHS = LHS->IgnoreParenCasts();
390 RHS = RHS->IgnoreParenCasts();
391
392 const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS);
393 if (!LHS_DR)
394 return false;
395
396 const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(LHS_DR->getDecl());
397 if (!PD)
398 return false;
399
400 const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS);
401 if (!RHS_DR)
402 return false;
403
404 return PD == RHS_DR->getDecl();
405}
406
407// Check for self casts truncating/extending a variable
408bool IdempotentOperationChecker::isTruncationExtensionAssignment(
409 const Expr *LHS,
410 const Expr *RHS) {
411
412 const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS->IgnoreParenCasts());
413 if (!LHS_DR)
414 return false;
415
416 const VarDecl *VD = dyn_cast<VarDecl>(LHS_DR->getDecl());
417 if (!VD)
418 return false;
419
420 const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS->IgnoreParenCasts());
421 if (!RHS_DR)
422 return false;
423
424 if (VD != RHS_DR->getDecl())
425 return false;
426
427 return dyn_cast<DeclRefExpr>(RHS->IgnoreParens()) == NULL;
428}
429
Tom Carea7a8a452010-08-12 22:45:47 +0000430// Returns false if a path to this block was not completely analyzed, or true
431// otherwise.
432bool IdempotentOperationChecker::PathWasCompletelyAnalyzed(
433 const CFG *C,
434 const CFGBlock *CB,
435 const GRCoreEngine &CE) {
436 std::deque<const CFGBlock *> WorkList;
437 llvm::SmallSet<unsigned, 8> Aborted;
438 llvm::SmallSet<unsigned, 128> Visited;
Tom Caredb2fa8a2010-07-06 21:43:29 +0000439
Tom Carea7a8a452010-08-12 22:45:47 +0000440 // Create a set of all aborted blocks
441 typedef GRCoreEngine::BlocksAborted::const_iterator AbortedIterator;
442 for (AbortedIterator I = CE.blocks_aborted_begin(),
443 E = CE.blocks_aborted_end(); I != E; ++I) {
444 const BlockEdge &BE = I->first;
Tom Caredb2fa8a2010-07-06 21:43:29 +0000445
Tom Carea7a8a452010-08-12 22:45:47 +0000446 // The destination block on the BlockEdge is the first block that was not
447 // analyzed.
448 Aborted.insert(BE.getDst()->getBlockID());
Ted Kremenek45329312010-07-17 00:40:32 +0000449 }
Tom Caredb2fa8a2010-07-06 21:43:29 +0000450
Tom Carea7a8a452010-08-12 22:45:47 +0000451 // Save the entry block ID for early exiting
452 unsigned EntryBlockID = C->getEntry().getBlockID();
Tom Caredb2fa8a2010-07-06 21:43:29 +0000453
Tom Carea7a8a452010-08-12 22:45:47 +0000454 // Create initial node
455 WorkList.push_back(CB);
456
457 while (!WorkList.empty()) {
458 const CFGBlock *Head = WorkList.front();
459 WorkList.pop_front();
460 Visited.insert(Head->getBlockID());
461
462 // If we found the entry block, then there exists a path from the target
463 // node to the entry point of this function -> the path was completely
464 // analyzed.
465 if (Head->getBlockID() == EntryBlockID)
466 return true;
467
468 // If any of the aborted blocks are on the path to the beginning, then all
469 // paths to this block were not analyzed.
470 if (Aborted.count(Head->getBlockID()))
471 return false;
472
473 // Add the predecessors to the worklist unless we have already visited them
474 for (CFGBlock::const_pred_iterator I = Head->pred_begin();
475 I != Head->pred_end(); ++I)
476 if (!Visited.count((*I)->getBlockID()))
477 WorkList.push_back(*I);
478 }
479
480 // If we get to this point, there is no connection to the entry block or an
481 // aborted block. This path is unreachable and we can report the error.
482 return true;
483}
484
485// Recursive function that determines whether an expression contains any element
486// that varies. This could be due to a compile-time constant like sizeof. An
487// expression may also involve a variable that behaves like a constant. The
488// function returns true if the expression varies, and false otherwise.
489bool IdempotentOperationChecker::CanVary(const Expr *Ex, ASTContext &Ctx) {
490 // Parentheses and casts are irrelevant here
491 Ex = Ex->IgnoreParenCasts();
492
493 if (Ex->getLocStart().isMacroID())
494 return false;
495
496 switch (Ex->getStmtClass()) {
497 // Trivially true cases
498 case Stmt::ArraySubscriptExprClass:
499 case Stmt::MemberExprClass:
500 case Stmt::StmtExprClass:
501 case Stmt::CallExprClass:
502 case Stmt::VAArgExprClass:
503 case Stmt::ShuffleVectorExprClass:
504 return true;
505 default:
506 return true;
507
508 // Trivially false cases
509 case Stmt::IntegerLiteralClass:
510 case Stmt::CharacterLiteralClass:
511 case Stmt::FloatingLiteralClass:
512 case Stmt::PredefinedExprClass:
513 case Stmt::ImaginaryLiteralClass:
514 case Stmt::StringLiteralClass:
515 case Stmt::OffsetOfExprClass:
516 case Stmt::CompoundLiteralExprClass:
517 case Stmt::AddrLabelExprClass:
518 case Stmt::TypesCompatibleExprClass:
519 case Stmt::GNUNullExprClass:
520 case Stmt::InitListExprClass:
521 case Stmt::DesignatedInitExprClass:
522 case Stmt::BlockExprClass:
523 case Stmt::BlockDeclRefExprClass:
524 return false;
525
526 // Cases requiring custom logic
527 case Stmt::SizeOfAlignOfExprClass: {
528 const SizeOfAlignOfExpr *SE = cast<const SizeOfAlignOfExpr>(Ex);
529 if (!SE->isSizeOf())
530 return false;
531 return SE->getTypeOfArgument()->isVariableArrayType();
532 }
533 case Stmt::DeclRefExprClass:
Tom Care50e8ac22010-08-16 21:43:52 +0000534 return !isPseudoConstant(cast<DeclRefExpr>(Ex));
Tom Carea7a8a452010-08-12 22:45:47 +0000535
536 // The next cases require recursion for subexpressions
537 case Stmt::BinaryOperatorClass: {
538 const BinaryOperator *B = cast<const BinaryOperator>(Ex);
539 return CanVary(B->getRHS(), Ctx) || CanVary(B->getLHS(), Ctx);
540 }
541 case Stmt::UnaryOperatorClass: {
542 const UnaryOperator *U = cast<const UnaryOperator>(Ex);
Eli Friedmande7e6622010-08-13 01:36:11 +0000543 // Handle trivial case first
Tom Carea7a8a452010-08-12 22:45:47 +0000544 switch (U->getOpcode()) {
545 case UnaryOperator::Extension:
Tom Carea7a8a452010-08-12 22:45:47 +0000546 return false;
547 default:
548 return CanVary(U->getSubExpr(), Ctx);
549 }
550 }
551 case Stmt::ChooseExprClass:
552 return CanVary(cast<const ChooseExpr>(Ex)->getChosenSubExpr(Ctx), Ctx);
553 case Stmt::ConditionalOperatorClass:
554 return CanVary(cast<const ConditionalOperator>(Ex)->getCond(), Ctx);
555 }
Tom Caredb2fa8a2010-07-06 21:43:29 +0000556}
557
Tom Care50e8ac22010-08-16 21:43:52 +0000558// Returns true if a DeclRefExpr behaves like a constant.
559bool IdempotentOperationChecker::isPseudoConstant(const DeclRefExpr *DR) {
560 // Check for an enum
561 if (isa<EnumConstantDecl>(DR->getDecl()))
562 return true;
563
564 // Check for a static variable
565 // FIXME: Analysis should model static vars
566 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
567 if (VD->isStaticLocal())
568 return true;
569
570 return false;
571}