blob: 2cfcaa44d4b905da3ca89831b56ebf7fa525c97c [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 Caredb34ab72010-08-23 19:51:57 +000047#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
Tom Caredb2fa8a2010-07-06 21:43:29 +000048#include "clang/Checker/BugReporter/BugType.h"
Tom Carea9fbf5b2010-07-27 23:26:07 +000049#include "clang/Checker/PathSensitive/CheckerHelpers.h"
Tom Caredb2fa8a2010-07-06 21:43:29 +000050#include "clang/Checker/PathSensitive/CheckerVisitor.h"
Tom Carea7a8a452010-08-12 22:45:47 +000051#include "clang/Checker/PathSensitive/GRCoreEngine.h"
Tom Caredb2fa8a2010-07-06 21:43:29 +000052#include "clang/Checker/PathSensitive/SVals.h"
53#include "clang/AST/Stmt.h"
54#include "llvm/ADT/DenseMap.h"
Tom Carea7a8a452010-08-12 22:45:47 +000055#include "llvm/ADT/SmallSet.h"
Chandler Carruth256565b2010-07-07 00:07:37 +000056#include "llvm/Support/ErrorHandling.h"
Tom Carea7a8a452010-08-12 22:45:47 +000057#include <deque>
Tom Caredb2fa8a2010-07-06 21:43:29 +000058
59using namespace clang;
60
61namespace {
62class IdempotentOperationChecker
63 : public CheckerVisitor<IdempotentOperationChecker> {
64 public:
65 static void *getTag();
66 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
Tom Carebc42c532010-08-03 01:55:07 +000067 void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, GRExprEngine &Eng);
Tom Caredb2fa8a2010-07-06 21:43:29 +000068
69 private:
70 // Our assumption about a particular operation.
Ted Kremenekfe97fa12010-08-02 20:33:02 +000071 enum Assumption { Possible = 0, Impossible, Equal, LHSis1, RHSis1, LHSis0,
Tom Caredb2fa8a2010-07-06 21:43:29 +000072 RHSis0 };
73
74 void UpdateAssumption(Assumption &A, const Assumption &New);
75
Tom Care245adab2010-08-18 21:17:24 +000076 // False positive reduction methods
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);
Tom Care245adab2010-08-18 21:17:24 +000083 static bool CanVary(const Expr *Ex, AnalysisContext *AC);
84 static bool isConstantOrPseudoConstant(const DeclRefExpr *DR,
85 AnalysisContext *AC);
Tom Caredb34ab72010-08-23 19:51:57 +000086 static bool containsNonLocalVarDecl(const Stmt *S);
Tom Caredb2fa8a2010-07-06 21:43:29 +000087
88 // Hash table
Tom Carea7a8a452010-08-12 22:45:47 +000089 typedef llvm::DenseMap<const BinaryOperator *,
90 std::pair<Assumption, AnalysisContext*> >
91 AssumptionMap;
Tom Caredb2fa8a2010-07-06 21:43:29 +000092 AssumptionMap hash;
93};
94}
95
96void *IdempotentOperationChecker::getTag() {
97 static int x = 0;
98 return &x;
99}
100
101void clang::RegisterIdempotentOperationChecker(GRExprEngine &Eng) {
102 Eng.registerCheck(new IdempotentOperationChecker());
103}
104
105void IdempotentOperationChecker::PreVisitBinaryOperator(
106 CheckerContext &C,
107 const BinaryOperator *B) {
Ted Kremenekfe97fa12010-08-02 20:33:02 +0000108 // Find or create an entry in the hash for this BinaryOperator instance.
109 // If we haven't done a lookup before, it will get default initialized to
110 // 'Possible'.
Tom Carea7a8a452010-08-12 22:45:47 +0000111 std::pair<Assumption, AnalysisContext *> &Data = hash[B];
112 Assumption &A = Data.first;
Tom Care245adab2010-08-18 21:17:24 +0000113 AnalysisContext *AC = C.getCurrentAnalysisContext();
114 Data.second = AC;
Tom Caredb2fa8a2010-07-06 21:43:29 +0000115
116 // If we already have visited this node on a path that does not contain an
117 // idempotent operation, return immediately.
118 if (A == Impossible)
119 return;
120
Tom Carea7a8a452010-08-12 22:45:47 +0000121 // Retrieve both sides of the operator and determine if they can vary (which
122 // may mean this is a false positive.
Tom Caredb2fa8a2010-07-06 21:43:29 +0000123 const Expr *LHS = B->getLHS();
124 const Expr *RHS = B->getRHS();
Tom Care245adab2010-08-18 21:17:24 +0000125
Tom Caredb34ab72010-08-23 19:51:57 +0000126 // At this stage we can calculate whether each side contains a false positive
127 // that applies to all operators. We only need to calculate this the first
128 // time.
129 bool LHSContainsFalsePositive = false, RHSContainsFalsePositive = false;
Tom Care245adab2010-08-18 21:17:24 +0000130 if (A == Possible) {
Tom Caredb34ab72010-08-23 19:51:57 +0000131 // An expression contains a false positive if it can't vary, or if it
132 // contains a known false positive VarDecl.
133 LHSContainsFalsePositive = !CanVary(LHS, AC)
134 || containsNonLocalVarDecl(LHS);
135 RHSContainsFalsePositive = !CanVary(RHS, AC)
136 || containsNonLocalVarDecl(RHS);
Tom Care245adab2010-08-18 21:17:24 +0000137 }
Tom Caredb2fa8a2010-07-06 21:43:29 +0000138
139 const GRState *state = C.getState();
140
141 SVal LHSVal = state->getSVal(LHS);
142 SVal RHSVal = state->getSVal(RHS);
143
144 // If either value is unknown, we can't be 100% sure of all paths.
145 if (LHSVal.isUnknownOrUndef() || RHSVal.isUnknownOrUndef()) {
146 A = Impossible;
147 return;
148 }
149 BinaryOperator::Opcode Op = B->getOpcode();
150
151 // Dereference the LHS SVal if this is an assign operation
152 switch (Op) {
153 default:
154 break;
155
156 // Fall through intentional
157 case BinaryOperator::AddAssign:
158 case BinaryOperator::SubAssign:
159 case BinaryOperator::MulAssign:
160 case BinaryOperator::DivAssign:
161 case BinaryOperator::AndAssign:
162 case BinaryOperator::OrAssign:
163 case BinaryOperator::XorAssign:
164 case BinaryOperator::ShlAssign:
165 case BinaryOperator::ShrAssign:
166 case BinaryOperator::Assign:
167 // Assign statements have one extra level of indirection
168 if (!isa<Loc>(LHSVal)) {
169 A = Impossible;
170 return;
171 }
172 LHSVal = state->getSVal(cast<Loc>(LHSVal));
173 }
174
175
176 // We now check for various cases which result in an idempotent operation.
177
178 // x op x
179 switch (Op) {
180 default:
181 break; // We don't care about any other operators.
182
183 // Fall through intentional
Tom Caredf4ca422010-07-16 20:41:41 +0000184 case BinaryOperator::Assign:
185 // x Assign x has a few more false positives we can check for
186 if (isParameterSelfAssign(RHS, LHS)
187 || isTruncationExtensionAssignment(RHS, LHS)) {
188 A = Impossible;
189 return;
190 }
191
Tom Caredb2fa8a2010-07-06 21:43:29 +0000192 case BinaryOperator::SubAssign:
193 case BinaryOperator::DivAssign:
194 case BinaryOperator::AndAssign:
195 case BinaryOperator::OrAssign:
196 case BinaryOperator::XorAssign:
Tom Caredb2fa8a2010-07-06 21:43:29 +0000197 case BinaryOperator::Sub:
198 case BinaryOperator::Div:
199 case BinaryOperator::And:
200 case BinaryOperator::Or:
201 case BinaryOperator::Xor:
202 case BinaryOperator::LOr:
203 case BinaryOperator::LAnd:
Tom Caredb34ab72010-08-23 19:51:57 +0000204 if (LHSVal != RHSVal || LHSContainsFalsePositive
205 || RHSContainsFalsePositive)
Tom Caredb2fa8a2010-07-06 21:43:29 +0000206 break;
207 UpdateAssumption(A, Equal);
208 return;
209 }
210
211 // x op 1
212 switch (Op) {
213 default:
214 break; // We don't care about any other operators.
215
216 // Fall through intentional
217 case BinaryOperator::MulAssign:
218 case BinaryOperator::DivAssign:
219 case BinaryOperator::Mul:
220 case BinaryOperator::Div:
221 case BinaryOperator::LOr:
222 case BinaryOperator::LAnd:
Tom Caredb34ab72010-08-23 19:51:57 +0000223 if (!RHSVal.isConstant(1) || RHSContainsFalsePositive)
Tom Caredb2fa8a2010-07-06 21:43:29 +0000224 break;
225 UpdateAssumption(A, RHSis1);
226 return;
227 }
228
229 // 1 op x
230 switch (Op) {
231 default:
232 break; // We don't care about any other operators.
233
234 // Fall through intentional
235 case BinaryOperator::MulAssign:
236 case BinaryOperator::Mul:
237 case BinaryOperator::LOr:
238 case BinaryOperator::LAnd:
Tom Caredb34ab72010-08-23 19:51:57 +0000239 if (!LHSVal.isConstant(1) || LHSContainsFalsePositive)
Tom Caredb2fa8a2010-07-06 21:43:29 +0000240 break;
241 UpdateAssumption(A, LHSis1);
242 return;
243 }
244
245 // x op 0
246 switch (Op) {
247 default:
248 break; // We don't care about any other operators.
249
250 // Fall through intentional
251 case BinaryOperator::AddAssign:
252 case BinaryOperator::SubAssign:
253 case BinaryOperator::MulAssign:
254 case BinaryOperator::AndAssign:
255 case BinaryOperator::OrAssign:
256 case BinaryOperator::XorAssign:
257 case BinaryOperator::Add:
258 case BinaryOperator::Sub:
259 case BinaryOperator::Mul:
260 case BinaryOperator::And:
261 case BinaryOperator::Or:
262 case BinaryOperator::Xor:
263 case BinaryOperator::Shl:
264 case BinaryOperator::Shr:
265 case BinaryOperator::LOr:
266 case BinaryOperator::LAnd:
Tom Caredb34ab72010-08-23 19:51:57 +0000267 if (!RHSVal.isConstant(0) || RHSContainsFalsePositive)
Tom Caredb2fa8a2010-07-06 21:43:29 +0000268 break;
269 UpdateAssumption(A, RHSis0);
270 return;
271 }
272
273 // 0 op x
274 switch (Op) {
275 default:
276 break; // We don't care about any other operators.
277
278 // Fall through intentional
279 //case BinaryOperator::AddAssign: // Common false positive
280 case BinaryOperator::SubAssign: // Check only if unsigned
281 case BinaryOperator::MulAssign:
282 case BinaryOperator::DivAssign:
283 case BinaryOperator::AndAssign:
284 //case BinaryOperator::OrAssign: // Common false positive
285 //case BinaryOperator::XorAssign: // Common false positive
286 case BinaryOperator::ShlAssign:
287 case BinaryOperator::ShrAssign:
288 case BinaryOperator::Add:
289 case BinaryOperator::Sub:
290 case BinaryOperator::Mul:
291 case BinaryOperator::Div:
292 case BinaryOperator::And:
293 case BinaryOperator::Or:
294 case BinaryOperator::Xor:
295 case BinaryOperator::Shl:
296 case BinaryOperator::Shr:
297 case BinaryOperator::LOr:
298 case BinaryOperator::LAnd:
Tom Caredb34ab72010-08-23 19:51:57 +0000299 if (!LHSVal.isConstant(0) || LHSContainsFalsePositive)
Tom Caredb2fa8a2010-07-06 21:43:29 +0000300 break;
301 UpdateAssumption(A, LHSis0);
302 return;
303 }
304
305 // If we get to this point, there has been a valid use of this operation.
306 A = Impossible;
307}
308
309void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
Ted Kremenek3e5637f2010-07-27 18:49:08 +0000310 BugReporter &BR,
Tom Carebc42c532010-08-03 01:55:07 +0000311 GRExprEngine &Eng) {
Tom Caredb2fa8a2010-07-06 21:43:29 +0000312 // Iterate over the hash to see if we have any paths with definite
313 // idempotent operations.
Tom Carea7a8a452010-08-12 22:45:47 +0000314 for (AssumptionMap::const_iterator i = hash.begin(); i != hash.end(); ++i) {
315 // Unpack the hash contents
316 const std::pair<Assumption, AnalysisContext *> &Data = i->second;
317 const Assumption &A = Data.first;
318 AnalysisContext *AC = Data.second;
Ted Kremenek3e5637f2010-07-27 18:49:08 +0000319
Tom Carea7a8a452010-08-12 22:45:47 +0000320 const BinaryOperator *B = i->first;
Tom Caredb2fa8a2010-07-06 21:43:29 +0000321
Tom Carea7a8a452010-08-12 22:45:47 +0000322 if (A == Impossible)
323 continue;
324
325 // If the analyzer did not finish, check to see if we can still emit this
326 // warning
327 if (Eng.hasWorkRemaining()) {
328 const CFGStmtMap *CBM = CFGStmtMap::Build(AC->getCFG(),
329 &AC->getParentMap());
330
331 // If we can trace back
332 if (!PathWasCompletelyAnalyzed(AC->getCFG(),
333 CBM->getBlock(B),
334 Eng.getCoreEngine()))
335 continue;
336
337 delete CBM;
Tom Caredb2fa8a2010-07-06 21:43:29 +0000338 }
Tom Carea7a8a452010-08-12 22:45:47 +0000339
340 // Select the error message.
341 llvm::SmallString<128> buf;
342 llvm::raw_svector_ostream os(buf);
343 switch (A) {
344 case Equal:
345 if (B->getOpcode() == BinaryOperator::Assign)
346 os << "Assigned value is always the same as the existing value";
347 else
348 os << "Both operands to '" << B->getOpcodeStr()
349 << "' always have the same value";
350 break;
351 case LHSis1:
352 os << "The left operand to '" << B->getOpcodeStr() << "' is always 1";
353 break;
354 case RHSis1:
355 os << "The right operand to '" << B->getOpcodeStr() << "' is always 1";
356 break;
357 case LHSis0:
358 os << "The left operand to '" << B->getOpcodeStr() << "' is always 0";
359 break;
360 case RHSis0:
361 os << "The right operand to '" << B->getOpcodeStr() << "' is always 0";
362 break;
363 case Possible:
364 llvm_unreachable("Operation was never marked with an assumption");
365 case Impossible:
366 llvm_unreachable(0);
367 }
368
369 // Create the SourceRange Arrays
370 SourceRange S[2] = { i->first->getLHS()->getSourceRange(),
371 i->first->getRHS()->getSourceRange() };
372 BR.EmitBasicReport("Idempotent operation", "Dead code",
373 os.str(), i->first->getOperatorLoc(), S, 2);
Tom Caredb2fa8a2010-07-06 21:43:29 +0000374 }
375}
376
377// Updates the current assumption given the new assumption
378inline void IdempotentOperationChecker::UpdateAssumption(Assumption &A,
379 const Assumption &New) {
380 switch (A) {
381 // If we don't currently have an assumption, set it
382 case Possible:
383 A = New;
384 return;
385
386 // If we have determined that a valid state happened, ignore the new
387 // assumption.
388 case Impossible:
389 return;
390
391 // Any other case means that we had a different assumption last time. We don't
392 // currently support mixing assumptions for diagnostic reasons, so we set
393 // our assumption to be impossible.
394 default:
395 A = Impossible;
396 return;
397 }
398}
399
Tom Caredf4ca422010-07-16 20:41:41 +0000400// Check for a statement were a parameter is self assigned (to avoid an unused
401// variable warning)
402bool IdempotentOperationChecker::isParameterSelfAssign(const Expr *LHS,
403 const Expr *RHS) {
404 LHS = LHS->IgnoreParenCasts();
405 RHS = RHS->IgnoreParenCasts();
406
407 const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS);
408 if (!LHS_DR)
409 return false;
410
411 const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(LHS_DR->getDecl());
412 if (!PD)
413 return false;
414
415 const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS);
416 if (!RHS_DR)
417 return false;
418
419 return PD == RHS_DR->getDecl();
420}
421
422// Check for self casts truncating/extending a variable
423bool IdempotentOperationChecker::isTruncationExtensionAssignment(
424 const Expr *LHS,
425 const Expr *RHS) {
426
427 const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS->IgnoreParenCasts());
428 if (!LHS_DR)
429 return false;
430
431 const VarDecl *VD = dyn_cast<VarDecl>(LHS_DR->getDecl());
432 if (!VD)
433 return false;
434
435 const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS->IgnoreParenCasts());
436 if (!RHS_DR)
437 return false;
438
439 if (VD != RHS_DR->getDecl())
440 return false;
441
442 return dyn_cast<DeclRefExpr>(RHS->IgnoreParens()) == NULL;
443}
444
Tom Carea7a8a452010-08-12 22:45:47 +0000445// Returns false if a path to this block was not completely analyzed, or true
446// otherwise.
447bool IdempotentOperationChecker::PathWasCompletelyAnalyzed(
448 const CFG *C,
449 const CFGBlock *CB,
450 const GRCoreEngine &CE) {
451 std::deque<const CFGBlock *> WorkList;
452 llvm::SmallSet<unsigned, 8> Aborted;
453 llvm::SmallSet<unsigned, 128> Visited;
Tom Caredb2fa8a2010-07-06 21:43:29 +0000454
Tom Carea7a8a452010-08-12 22:45:47 +0000455 // Create a set of all aborted blocks
456 typedef GRCoreEngine::BlocksAborted::const_iterator AbortedIterator;
457 for (AbortedIterator I = CE.blocks_aborted_begin(),
458 E = CE.blocks_aborted_end(); I != E; ++I) {
459 const BlockEdge &BE = I->first;
Tom Caredb2fa8a2010-07-06 21:43:29 +0000460
Tom Carea7a8a452010-08-12 22:45:47 +0000461 // The destination block on the BlockEdge is the first block that was not
462 // analyzed.
463 Aborted.insert(BE.getDst()->getBlockID());
Ted Kremenek45329312010-07-17 00:40:32 +0000464 }
Tom Caredb2fa8a2010-07-06 21:43:29 +0000465
Tom Carea7a8a452010-08-12 22:45:47 +0000466 // Save the entry block ID for early exiting
467 unsigned EntryBlockID = C->getEntry().getBlockID();
Tom Caredb2fa8a2010-07-06 21:43:29 +0000468
Tom Carea7a8a452010-08-12 22:45:47 +0000469 // Create initial node
470 WorkList.push_back(CB);
471
472 while (!WorkList.empty()) {
473 const CFGBlock *Head = WorkList.front();
474 WorkList.pop_front();
475 Visited.insert(Head->getBlockID());
476
477 // If we found the entry block, then there exists a path from the target
478 // node to the entry point of this function -> the path was completely
479 // analyzed.
480 if (Head->getBlockID() == EntryBlockID)
481 return true;
482
483 // If any of the aborted blocks are on the path to the beginning, then all
484 // paths to this block were not analyzed.
485 if (Aborted.count(Head->getBlockID()))
486 return false;
487
488 // Add the predecessors to the worklist unless we have already visited them
489 for (CFGBlock::const_pred_iterator I = Head->pred_begin();
490 I != Head->pred_end(); ++I)
491 if (!Visited.count((*I)->getBlockID()))
492 WorkList.push_back(*I);
493 }
494
495 // If we get to this point, there is no connection to the entry block or an
496 // aborted block. This path is unreachable and we can report the error.
497 return true;
498}
499
500// Recursive function that determines whether an expression contains any element
501// that varies. This could be due to a compile-time constant like sizeof. An
502// expression may also involve a variable that behaves like a constant. The
503// function returns true if the expression varies, and false otherwise.
Tom Care245adab2010-08-18 21:17:24 +0000504bool IdempotentOperationChecker::CanVary(const Expr *Ex,
505 AnalysisContext *AC) {
Tom Carea7a8a452010-08-12 22:45:47 +0000506 // Parentheses and casts are irrelevant here
507 Ex = Ex->IgnoreParenCasts();
508
509 if (Ex->getLocStart().isMacroID())
510 return false;
511
512 switch (Ex->getStmtClass()) {
513 // Trivially true cases
514 case Stmt::ArraySubscriptExprClass:
515 case Stmt::MemberExprClass:
516 case Stmt::StmtExprClass:
517 case Stmt::CallExprClass:
518 case Stmt::VAArgExprClass:
519 case Stmt::ShuffleVectorExprClass:
520 return true;
521 default:
522 return true;
523
524 // Trivially false cases
525 case Stmt::IntegerLiteralClass:
526 case Stmt::CharacterLiteralClass:
527 case Stmt::FloatingLiteralClass:
528 case Stmt::PredefinedExprClass:
529 case Stmt::ImaginaryLiteralClass:
530 case Stmt::StringLiteralClass:
531 case Stmt::OffsetOfExprClass:
532 case Stmt::CompoundLiteralExprClass:
533 case Stmt::AddrLabelExprClass:
534 case Stmt::TypesCompatibleExprClass:
535 case Stmt::GNUNullExprClass:
536 case Stmt::InitListExprClass:
537 case Stmt::DesignatedInitExprClass:
538 case Stmt::BlockExprClass:
539 case Stmt::BlockDeclRefExprClass:
540 return false;
541
542 // Cases requiring custom logic
543 case Stmt::SizeOfAlignOfExprClass: {
544 const SizeOfAlignOfExpr *SE = cast<const SizeOfAlignOfExpr>(Ex);
545 if (!SE->isSizeOf())
546 return false;
547 return SE->getTypeOfArgument()->isVariableArrayType();
548 }
549 case Stmt::DeclRefExprClass:
Tom Care245adab2010-08-18 21:17:24 +0000550 return !isConstantOrPseudoConstant(cast<DeclRefExpr>(Ex), AC);
Tom Carea7a8a452010-08-12 22:45:47 +0000551
552 // The next cases require recursion for subexpressions
553 case Stmt::BinaryOperatorClass: {
554 const BinaryOperator *B = cast<const BinaryOperator>(Ex);
Tom Care245adab2010-08-18 21:17:24 +0000555 return CanVary(B->getRHS(), AC)
556 || CanVary(B->getLHS(), AC);
Tom Carea7a8a452010-08-12 22:45:47 +0000557 }
558 case Stmt::UnaryOperatorClass: {
559 const UnaryOperator *U = cast<const UnaryOperator>(Ex);
Eli Friedmande7e6622010-08-13 01:36:11 +0000560 // Handle trivial case first
Tom Carea7a8a452010-08-12 22:45:47 +0000561 switch (U->getOpcode()) {
562 case UnaryOperator::Extension:
Tom Carea7a8a452010-08-12 22:45:47 +0000563 return false;
564 default:
Tom Care245adab2010-08-18 21:17:24 +0000565 return CanVary(U->getSubExpr(), AC);
Tom Carea7a8a452010-08-12 22:45:47 +0000566 }
567 }
568 case Stmt::ChooseExprClass:
Tom Care245adab2010-08-18 21:17:24 +0000569 return CanVary(cast<const ChooseExpr>(Ex)->getChosenSubExpr(
570 AC->getASTContext()), AC);
Tom Carea7a8a452010-08-12 22:45:47 +0000571 case Stmt::ConditionalOperatorClass:
Tom Care245adab2010-08-18 21:17:24 +0000572 return CanVary(cast<const ConditionalOperator>(Ex)->getCond(), AC);
Tom Carea7a8a452010-08-12 22:45:47 +0000573 }
Tom Caredb2fa8a2010-07-06 21:43:29 +0000574}
575
Tom Care245adab2010-08-18 21:17:24 +0000576// Returns true if a DeclRefExpr is or behaves like a constant.
577bool IdempotentOperationChecker::isConstantOrPseudoConstant(
578 const DeclRefExpr *DR,
579 AnalysisContext *AC) {
580 // Check if the type of the Decl is const-qualified
581 if (DR->getType().isConstQualified())
582 return true;
583
Tom Care50e8ac22010-08-16 21:43:52 +0000584 // Check for an enum
585 if (isa<EnumConstantDecl>(DR->getDecl()))
586 return true;
587
Tom Caredb34ab72010-08-23 19:51:57 +0000588 const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
589 if (!VD)
Tom Care245adab2010-08-18 21:17:24 +0000590 return true;
591
Tom Caredb34ab72010-08-23 19:51:57 +0000592 // Check if the Decl behaves like a constant. This check also takes care of
593 // static variables, which can only change between function calls if they are
594 // modified in the AST.
595 PseudoConstantAnalysis *PCA = AC->getPseudoConstantAnalysis();
596 if (PCA->isPseudoConstant(VD))
597 return true;
598
599 return false;
600}
601
602// Recursively find any substatements containing VarDecl's with storage other
603// than local
604bool IdempotentOperationChecker::containsNonLocalVarDecl(const Stmt *S) {
605 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
606
607 if (DR)
608 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
609 if (!VD->hasLocalStorage())
610 return true;
611
612 for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
613 ++I)
614 if (const Stmt *child = *I)
615 if (containsNonLocalVarDecl(child))
616 return true;
617
Tom Care50e8ac22010-08-16 21:43:52 +0000618 return false;
619}