clang  6.0.0svn
IdenticalExprChecker.cpp
Go to the documentation of this file.
1 //== IdenticalExprChecker.cpp - Identical expression checker----------------==//
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 /// \file
11 /// \brief This defines IdenticalExprChecker, a check that warns about
12 /// unintended use of identical expressions.
13 ///
14 /// It checks for use of identical expressions with comparison operators and
15 /// inside conditional expressions.
16 ///
17 //===----------------------------------------------------------------------===//
18 
19 #include "ClangSACheckers.h"
25 
26 using namespace clang;
27 using namespace ento;
28 
29 static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
30  const Stmt *Stmt2, bool IgnoreSideEffects = false);
31 //===----------------------------------------------------------------------===//
32 // FindIdenticalExprVisitor - Identify nodes using identical expressions.
33 //===----------------------------------------------------------------------===//
34 
35 namespace {
36 class FindIdenticalExprVisitor
37  : public RecursiveASTVisitor<FindIdenticalExprVisitor> {
38  BugReporter &BR;
39  const CheckerBase *Checker;
41 public:
42  explicit FindIdenticalExprVisitor(BugReporter &B,
43  const CheckerBase *Checker,
45  : BR(B), Checker(Checker), AC(A) {}
46  // FindIdenticalExprVisitor only visits nodes
47  // that are binary operators, if statements or
48  // conditional operators.
49  bool VisitBinaryOperator(const BinaryOperator *B);
50  bool VisitIfStmt(const IfStmt *I);
51  bool VisitConditionalOperator(const ConditionalOperator *C);
52 
53 private:
54  void reportIdenticalExpr(const BinaryOperator *B, bool CheckBitwise,
56  void checkBitwiseOrLogicalOp(const BinaryOperator *B, bool CheckBitwise);
57  void checkComparisonOp(const BinaryOperator *B);
58 };
59 } // end anonymous namespace
60 
61 void FindIdenticalExprVisitor::reportIdenticalExpr(const BinaryOperator *B,
62  bool CheckBitwise,
64  StringRef Message;
65  if (CheckBitwise)
66  Message = "identical expressions on both sides of bitwise operator";
67  else
68  Message = "identical expressions on both sides of logical operator";
69 
71  PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
72  BR.EmitBasicReport(AC->getDecl(), Checker,
73  "Use of identical expressions",
75  Message, ELoc, Sr);
76 }
77 
78 void FindIdenticalExprVisitor::checkBitwiseOrLogicalOp(const BinaryOperator *B,
79  bool CheckBitwise) {
80  SourceRange Sr[2];
81 
82  const Expr *LHS = B->getLHS();
83  const Expr *RHS = B->getRHS();
84 
85  // Split operators as long as we still have operators to split on. We will
86  // get called for every binary operator in an expression so there is no need
87  // to check every one against each other here, just the right most one with
88  // the others.
89  while (const BinaryOperator *B2 = dyn_cast<BinaryOperator>(LHS)) {
90  if (B->getOpcode() != B2->getOpcode())
91  break;
92  if (isIdenticalStmt(AC->getASTContext(), RHS, B2->getRHS())) {
93  Sr[0] = RHS->getSourceRange();
94  Sr[1] = B2->getRHS()->getSourceRange();
95  reportIdenticalExpr(B, CheckBitwise, Sr);
96  }
97  LHS = B2->getLHS();
98  }
99 
100  if (isIdenticalStmt(AC->getASTContext(), RHS, LHS)) {
101  Sr[0] = RHS->getSourceRange();
102  Sr[1] = LHS->getSourceRange();
103  reportIdenticalExpr(B, CheckBitwise, Sr);
104  }
105 }
106 
107 bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) {
108  const Stmt *Stmt1 = I->getThen();
109  const Stmt *Stmt2 = I->getElse();
110 
111  // Check for identical inner condition:
112  //
113  // if (x<10) {
114  // if (x<10) {
115  // ..
116  if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(Stmt1)) {
117  if (!CS->body_empty()) {
118  const IfStmt *InnerIf = dyn_cast<IfStmt>(*CS->body_begin());
119  if (InnerIf && isIdenticalStmt(AC->getASTContext(), I->getCond(), InnerIf->getCond(), /*ignoreSideEffects=*/ false)) {
120  PathDiagnosticLocation ELoc(InnerIf->getCond(), BR.getSourceManager(), AC);
121  BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions",
123  "conditions of the inner and outer statements are identical",
124  ELoc);
125  }
126  }
127  }
128 
129  // Check for identical conditions:
130  //
131  // if (b) {
132  // foo1();
133  // } else if (b) {
134  // foo2();
135  // }
136  if (Stmt1 && Stmt2) {
137  const Expr *Cond1 = I->getCond();
138  const Stmt *Else = Stmt2;
139  while (const IfStmt *I2 = dyn_cast_or_null<IfStmt>(Else)) {
140  const Expr *Cond2 = I2->getCond();
141  if (isIdenticalStmt(AC->getASTContext(), Cond1, Cond2, false)) {
142  SourceRange Sr = Cond1->getSourceRange();
143  PathDiagnosticLocation ELoc(Cond2, BR.getSourceManager(), AC);
144  BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions",
146  "expression is identical to previous condition",
147  ELoc, Sr);
148  }
149  Else = I2->getElse();
150  }
151  }
152 
153  if (!Stmt1 || !Stmt2)
154  return true;
155 
156  // Special handling for code like:
157  //
158  // if (b) {
159  // i = 1;
160  // } else
161  // i = 1;
162  if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt1)) {
163  if (CompStmt->size() == 1)
164  Stmt1 = CompStmt->body_back();
165  }
166  if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt2)) {
167  if (CompStmt->size() == 1)
168  Stmt2 = CompStmt->body_back();
169  }
170 
171  if (isIdenticalStmt(AC->getASTContext(), Stmt1, Stmt2, true)) {
173  PathDiagnosticLocation::createBegin(I, BR.getSourceManager(), AC);
174  BR.EmitBasicReport(AC->getDecl(), Checker,
175  "Identical branches",
177  "true and false branches are identical", ELoc);
178  }
179  return true;
180 }
181 
182 bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) {
184 
186  checkBitwiseOrLogicalOp(B, true);
187 
189  checkBitwiseOrLogicalOp(B, false);
190 
192  checkComparisonOp(B);
193 
194  // We want to visit ALL nodes (subexpressions of binary comparison
195  // expressions too) that contains comparison operators.
196  // True is always returned to traverse ALL nodes.
197  return true;
198 }
199 
200 void FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) {
202 
203  //
204  // Special case for floating-point representation.
205  //
206  // If expressions on both sides of comparison operator are of type float,
207  // then for some comparison operators no warning shall be
208  // reported even if the expressions are identical from a symbolic point of
209  // view. Comparison between expressions, declared variables and literals
210  // are treated differently.
211  //
212  // != and == between float literals that have the same value should NOT warn.
213  // < > between float literals that have the same value SHOULD warn.
214  //
215  // != and == between the same float declaration should NOT warn.
216  // < > between the same float declaration SHOULD warn.
217  //
218  // != and == between eq. expressions that evaluates into float
219  // should NOT warn.
220  // < > between eq. expressions that evaluates into float
221  // should NOT warn.
222  //
223  const Expr *LHS = B->getLHS()->IgnoreParenImpCasts();
224  const Expr *RHS = B->getRHS()->IgnoreParenImpCasts();
225 
226  const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(LHS);
227  const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(RHS);
228  const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(LHS);
229  const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(RHS);
230  if ((DeclRef1) && (DeclRef2)) {
231  if ((DeclRef1->getType()->hasFloatingRepresentation()) &&
232  (DeclRef2->getType()->hasFloatingRepresentation())) {
233  if (DeclRef1->getDecl() == DeclRef2->getDecl()) {
234  if ((Op == BO_EQ) || (Op == BO_NE)) {
235  return;
236  }
237  }
238  }
239  } else if ((FloatLit1) && (FloatLit2)) {
240  if (FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue())) {
241  if ((Op == BO_EQ) || (Op == BO_NE)) {
242  return;
243  }
244  }
245  } else if (LHS->getType()->hasFloatingRepresentation()) {
246  // If any side of comparison operator still has floating-point
247  // representation, then it's an expression. Don't warn.
248  // Here only LHS is checked since RHS will be implicit casted to float.
249  return;
250  } else {
251  // No special case with floating-point representation, report as usual.
252  }
253 
254  if (isIdenticalStmt(AC->getASTContext(), B->getLHS(), B->getRHS())) {
256  PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
257  StringRef Message;
258  if (Op == BO_Cmp)
259  Message = "comparison of identical expressions always evaluates to "
260  "'equal'";
261  else if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE)))
262  Message = "comparison of identical expressions always evaluates to true";
263  else
264  Message = "comparison of identical expressions always evaluates to false";
265  BR.EmitBasicReport(AC->getDecl(), Checker,
266  "Compare of identical expressions",
267  categories::LogicError, Message, ELoc);
268  }
269 }
270 
271 bool FindIdenticalExprVisitor::VisitConditionalOperator(
272  const ConditionalOperator *C) {
273 
274  // Check if expressions in conditional expression are identical
275  // from a symbolic point of view.
276 
277  if (isIdenticalStmt(AC->getASTContext(), C->getTrueExpr(),
278  C->getFalseExpr(), true)) {
281  C, BR.getSourceManager());
282 
283  SourceRange Sr[2];
284  Sr[0] = C->getTrueExpr()->getSourceRange();
285  Sr[1] = C->getFalseExpr()->getSourceRange();
286  BR.EmitBasicReport(
287  AC->getDecl(), Checker,
288  "Identical expressions in conditional expression",
290  "identical expressions on both sides of ':' in conditional expression",
291  ELoc, Sr);
292  }
293  // We want to visit ALL nodes (expressions in conditional
294  // expressions too) that contains conditional operators,
295  // thus always return true to traverse ALL nodes.
296  return true;
297 }
298 
299 /// \brief Determines whether two statement trees are identical regarding
300 /// operators and symbols.
301 ///
302 /// Exceptions: expressions containing macros or functions with possible side
303 /// effects are never considered identical.
304 /// Limitations: (t + u) and (u + t) are not considered identical.
305 /// t*(u + t) and t*u + t*t are not considered identical.
306 ///
307 static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
308  const Stmt *Stmt2, bool IgnoreSideEffects) {
309 
310  if (!Stmt1 || !Stmt2) {
311  return !Stmt1 && !Stmt2;
312  }
313 
314  // If Stmt1 & Stmt2 are of different class then they are not
315  // identical statements.
316  if (Stmt1->getStmtClass() != Stmt2->getStmtClass())
317  return false;
318 
319  const Expr *Expr1 = dyn_cast<Expr>(Stmt1);
320  const Expr *Expr2 = dyn_cast<Expr>(Stmt2);
321 
322  if (Expr1 && Expr2) {
323  // If Stmt1 has side effects then don't warn even if expressions
324  // are identical.
325  if (!IgnoreSideEffects && Expr1->HasSideEffects(Ctx))
326  return false;
327  // If either expression comes from a macro then don't warn even if
328  // the expressions are identical.
329  if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID()))
330  return false;
331 
332  // If all children of two expressions are identical, return true.
334  Expr::const_child_iterator I2 = Expr2->child_begin();
335  while (I1 != Expr1->child_end() && I2 != Expr2->child_end()) {
336  if (!*I1 || !*I2 || !isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects))
337  return false;
338  ++I1;
339  ++I2;
340  }
341  // If there are different number of children in the statements, return
342  // false.
343  if (I1 != Expr1->child_end())
344  return false;
345  if (I2 != Expr2->child_end())
346  return false;
347  }
348 
349  switch (Stmt1->getStmtClass()) {
350  default:
351  return false;
352  case Stmt::CallExprClass:
353  case Stmt::ArraySubscriptExprClass:
354  case Stmt::OMPArraySectionExprClass:
355  case Stmt::ImplicitCastExprClass:
356  case Stmt::ParenExprClass:
357  case Stmt::BreakStmtClass:
358  case Stmt::ContinueStmtClass:
359  case Stmt::NullStmtClass:
360  return true;
361  case Stmt::CStyleCastExprClass: {
362  const CStyleCastExpr* CastExpr1 = cast<CStyleCastExpr>(Stmt1);
363  const CStyleCastExpr* CastExpr2 = cast<CStyleCastExpr>(Stmt2);
364 
365  return CastExpr1->getTypeAsWritten() == CastExpr2->getTypeAsWritten();
366  }
367  case Stmt::ReturnStmtClass: {
368  const ReturnStmt *ReturnStmt1 = cast<ReturnStmt>(Stmt1);
369  const ReturnStmt *ReturnStmt2 = cast<ReturnStmt>(Stmt2);
370 
371  return isIdenticalStmt(Ctx, ReturnStmt1->getRetValue(),
372  ReturnStmt2->getRetValue(), IgnoreSideEffects);
373  }
374  case Stmt::ForStmtClass: {
375  const ForStmt *ForStmt1 = cast<ForStmt>(Stmt1);
376  const ForStmt *ForStmt2 = cast<ForStmt>(Stmt2);
377 
378  if (!isIdenticalStmt(Ctx, ForStmt1->getInit(), ForStmt2->getInit(),
379  IgnoreSideEffects))
380  return false;
381  if (!isIdenticalStmt(Ctx, ForStmt1->getCond(), ForStmt2->getCond(),
382  IgnoreSideEffects))
383  return false;
384  if (!isIdenticalStmt(Ctx, ForStmt1->getInc(), ForStmt2->getInc(),
385  IgnoreSideEffects))
386  return false;
387  if (!isIdenticalStmt(Ctx, ForStmt1->getBody(), ForStmt2->getBody(),
388  IgnoreSideEffects))
389  return false;
390  return true;
391  }
392  case Stmt::DoStmtClass: {
393  const DoStmt *DStmt1 = cast<DoStmt>(Stmt1);
394  const DoStmt *DStmt2 = cast<DoStmt>(Stmt2);
395 
396  if (!isIdenticalStmt(Ctx, DStmt1->getCond(), DStmt2->getCond(),
397  IgnoreSideEffects))
398  return false;
399  if (!isIdenticalStmt(Ctx, DStmt1->getBody(), DStmt2->getBody(),
400  IgnoreSideEffects))
401  return false;
402  return true;
403  }
404  case Stmt::WhileStmtClass: {
405  const WhileStmt *WStmt1 = cast<WhileStmt>(Stmt1);
406  const WhileStmt *WStmt2 = cast<WhileStmt>(Stmt2);
407 
408  if (!isIdenticalStmt(Ctx, WStmt1->getCond(), WStmt2->getCond(),
409  IgnoreSideEffects))
410  return false;
411  if (!isIdenticalStmt(Ctx, WStmt1->getBody(), WStmt2->getBody(),
412  IgnoreSideEffects))
413  return false;
414  return true;
415  }
416  case Stmt::IfStmtClass: {
417  const IfStmt *IStmt1 = cast<IfStmt>(Stmt1);
418  const IfStmt *IStmt2 = cast<IfStmt>(Stmt2);
419 
420  if (!isIdenticalStmt(Ctx, IStmt1->getCond(), IStmt2->getCond(),
421  IgnoreSideEffects))
422  return false;
423  if (!isIdenticalStmt(Ctx, IStmt1->getThen(), IStmt2->getThen(),
424  IgnoreSideEffects))
425  return false;
426  if (!isIdenticalStmt(Ctx, IStmt1->getElse(), IStmt2->getElse(),
427  IgnoreSideEffects))
428  return false;
429  return true;
430  }
431  case Stmt::CompoundStmtClass: {
432  const CompoundStmt *CompStmt1 = cast<CompoundStmt>(Stmt1);
433  const CompoundStmt *CompStmt2 = cast<CompoundStmt>(Stmt2);
434 
435  if (CompStmt1->size() != CompStmt2->size())
436  return false;
437 
439  CompoundStmt::const_body_iterator I2 = CompStmt2->body_begin();
440  while (I1 != CompStmt1->body_end() && I2 != CompStmt2->body_end()) {
441  if (!isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects))
442  return false;
443  ++I1;
444  ++I2;
445  }
446 
447  return true;
448  }
449  case Stmt::CompoundAssignOperatorClass:
450  case Stmt::BinaryOperatorClass: {
451  const BinaryOperator *BinOp1 = cast<BinaryOperator>(Stmt1);
452  const BinaryOperator *BinOp2 = cast<BinaryOperator>(Stmt2);
453  return BinOp1->getOpcode() == BinOp2->getOpcode();
454  }
455  case Stmt::CharacterLiteralClass: {
456  const CharacterLiteral *CharLit1 = cast<CharacterLiteral>(Stmt1);
457  const CharacterLiteral *CharLit2 = cast<CharacterLiteral>(Stmt2);
458  return CharLit1->getValue() == CharLit2->getValue();
459  }
460  case Stmt::DeclRefExprClass: {
461  const DeclRefExpr *DeclRef1 = cast<DeclRefExpr>(Stmt1);
462  const DeclRefExpr *DeclRef2 = cast<DeclRefExpr>(Stmt2);
463  return DeclRef1->getDecl() == DeclRef2->getDecl();
464  }
465  case Stmt::IntegerLiteralClass: {
466  const IntegerLiteral *IntLit1 = cast<IntegerLiteral>(Stmt1);
467  const IntegerLiteral *IntLit2 = cast<IntegerLiteral>(Stmt2);
468 
469  llvm::APInt I1 = IntLit1->getValue();
470  llvm::APInt I2 = IntLit2->getValue();
471  if (I1.getBitWidth() != I2.getBitWidth())
472  return false;
473  return I1 == I2;
474  }
475  case Stmt::FloatingLiteralClass: {
476  const FloatingLiteral *FloatLit1 = cast<FloatingLiteral>(Stmt1);
477  const FloatingLiteral *FloatLit2 = cast<FloatingLiteral>(Stmt2);
478  return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue());
479  }
480  case Stmt::StringLiteralClass: {
481  const StringLiteral *StringLit1 = cast<StringLiteral>(Stmt1);
482  const StringLiteral *StringLit2 = cast<StringLiteral>(Stmt2);
483  return StringLit1->getBytes() == StringLit2->getBytes();
484  }
485  case Stmt::MemberExprClass: {
486  const MemberExpr *MemberStmt1 = cast<MemberExpr>(Stmt1);
487  const MemberExpr *MemberStmt2 = cast<MemberExpr>(Stmt2);
488  return MemberStmt1->getMemberDecl() == MemberStmt2->getMemberDecl();
489  }
490  case Stmt::UnaryOperatorClass: {
491  const UnaryOperator *UnaryOp1 = cast<UnaryOperator>(Stmt1);
492  const UnaryOperator *UnaryOp2 = cast<UnaryOperator>(Stmt2);
493  return UnaryOp1->getOpcode() == UnaryOp2->getOpcode();
494  }
495  }
496 }
497 
498 //===----------------------------------------------------------------------===//
499 // FindIdenticalExprChecker
500 //===----------------------------------------------------------------------===//
501 
502 namespace {
503 class FindIdenticalExprChecker : public Checker<check::ASTCodeBody> {
504 public:
505  void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
506  BugReporter &BR) const {
507  FindIdenticalExprVisitor Visitor(BR, this, Mgr.getAnalysisDeclContext(D));
508  Visitor.TraverseDecl(const_cast<Decl *>(D));
509  }
510 };
511 } // end anonymous namespace
512 
513 void ento::registerIdenticalExprChecker(CheckerManager &Mgr) {
514  Mgr.registerChecker<FindIdenticalExprChecker>();
515 }
child_iterator child_begin()
Definition: Stmt.h:452
Expr * getInc()
Definition: Stmt.h:1237
const Stmt * getElse() const
Definition: Stmt.h:969
body_iterator body_end()
Definition: Stmt.h:626
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:2483
Expr * getCond()
Definition: Stmt.h:1127
Stmt - This represents one statement.
Definition: Stmt.h:66
IfStmt - This represents an if/then/else.
Definition: Stmt.h:929
bool isLogicalOp() const
Definition: Expr.h:3106
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
llvm::APFloat getValue() const
Definition: Expr.h:1405
Opcode getOpcode() const
Definition: Expr.h:3026
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g., it is a floating-point type or a vector thereof.
Definition: Type.cpp:1886
Stmt * getBody()
Definition: Stmt.h:1175
Expr * getFalseExpr() const
Definition: Expr.h:3312
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:149
AnalysisDeclContext contains the context data for the function or method under analysis.
const Expr * getRetValue() const
Definition: Stmt.cpp:925
BinaryOperatorKind
ForStmt - This represents a &#39;for (init;cond;inc)&#39; stmt.
Definition: Stmt.h:1203
static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, const Stmt *Stmt2, bool IgnoreSideEffects=false)
Determines whether two statement trees are identical regarding operators and symbols.
Stmt * getBody()
Definition: Stmt.h:1238
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2985
Stmt * getInit()
Definition: Stmt.h:1217
Expr * getCond()
Definition: Stmt.h:1236
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
QualType getTypeAsWritten() const
getTypeAsWritten - Returns the type that this expression is casting to, as written in the source code...
Definition: Expr.h:2911
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3269
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:595
ConstStmtIterator const_child_iterator
Definition: Stmt.h:441
unsigned getValue() const
Definition: Expr.h:1372
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition: Expr.cpp:2942
Expr - This represents one expression.
Definition: Expr.h:106
const Stmt * getThen() const
Definition: Stmt.h:967
Stmt * getBody()
Definition: Stmt.h:1130
unsigned size() const
Definition: Stmt.h:619
QualType getType() const
Definition: Expr.h:128
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:1413
UnaryOperator - This represents the unary-expression&#39;s (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
Definition: Expr.h:1717
ValueDecl * getDecl()
Definition: Expr.h:1041
CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr.cast]), which uses the syntax (Type)expr.
Definition: Expr.h:2922
Stmt *const * const_body_iterator
Definition: Stmt.h:635
DoStmt - This represents a &#39;do/while&#39; stmt.
Definition: Stmt.h:1154
bool isComparisonOp() const
Definition: Expr.h:3076
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:403
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
CHECKER * registerChecker()
Used to register checkers.
static PathDiagnosticLocation createConditionalColonLoc(const ConditionalOperator *CO, const SourceManager &SM)
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:216
Expr * getLHS() const
Definition: Expr.h:3029
Dataflow Directional Tag Classes.
StmtClass getStmtClass() const
Definition: Stmt.h:378
body_iterator body_begin()
Definition: Stmt.h:625
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
Definition: Expr.cpp:2552
llvm::APInt getValue() const
Definition: Expr.h:1279
bool isMacroID() const
Opcode getOpcode() const
Definition: Expr.h:1741
StringRef getBytes() const
Allow access to clients that need the byte representation, such as ASTWriterStmt::VisitStringLiteral(...
Definition: Expr.h:1565
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)
Create the location for the operator of the binary expression.
Expr * getCond()
Definition: Stmt.h:1172
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:2387
Expr * getTrueExpr() const
Definition: Expr.h:3307
WhileStmt - This represents a &#39;while&#39; stmt.
Definition: Stmt.h:1098
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:265
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1509
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:956
Expr * getRHS() const
Definition: Expr.h:3031
bool isBitwiseOp() const
Definition: Expr.h:3067
const Expr * getCond() const
Definition: Stmt.h:965
A trivial tuple used to represent a source range.
child_iterator child_end()
Definition: Stmt.h:453