diff options
Diffstat (limited to 'clang/Sema')
-rw-r--r-- | clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | clang/Sema/SemaChecking.cpp | 37 | ||||
-rw-r--r-- | clang/Sema/SemaExpr.cpp | 68 | ||||
-rw-r--r-- | clang/Sema/SemaUtil.h | 60 |
4 files changed, 101 insertions, 66 deletions
diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index 16d4cabb7eb..c8791467600 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -729,6 +729,8 @@ private: bool CheckBuiltinCFStringArgument(Expr* Arg); + + void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex); }; diff --git a/clang/Sema/SemaChecking.cpp b/clang/Sema/SemaChecking.cpp index c2e3817171d..cb22f03a31f 100644 --- a/clang/Sema/SemaChecking.cpp +++ b/clang/Sema/SemaChecking.cpp @@ -25,6 +25,8 @@ #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "SemaUtil.h" + using namespace clang; /// CheckFunctionCall - Check a direct function call for various correctness @@ -694,3 +696,38 @@ static DeclRefExpr* EvalVal(Expr *E) { return NULL; } } + +//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===// + +/// Check for comparisons of floating point operands using != and ==. +/// Issue a warning if these are no self-comparisons, as they are not likely +/// to do what the programmer intended. +void Sema::CheckFloatComparison(SourceLocation loc, Expr* lex, Expr *rex) { + bool EmitWarning = true; + + Expr* LeftExprSansParen = IgnoreParen(lex); + Expr* RightExprSansParen = IgnoreParen(rex); + + // Special case: check for x == x (which is OK). + // Do not emit warnings for such cases. + if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen)) + if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RightExprSansParen)) + if (DRL->getDecl() == DRR->getDecl()) + EmitWarning = false; + + // Check for comparisons with builtin types. + if (EmitWarning) + if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen)) + if (isCallBuiltin(CL)) + EmitWarning = false; + + if (EmitWarning) + if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen)) + if (isCallBuiltin(CR)) + EmitWarning = false; + + // Emit the diagnostic. + if (EmitWarning) + Diag(loc, diag::warn_floatingpoint_eq, + lex->getSourceRange(),rex->getSourceRange()); +} diff --git a/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp index 6c3b06e0155..a9cd41580bb 100644 --- a/clang/Sema/SemaExpr.cpp +++ b/clang/Sema/SemaExpr.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "SemaUtil.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" @@ -1213,42 +1214,6 @@ inline QualType Sema::CheckShiftOperands( // C99 6.5.7 return QualType(); } -// Utility method to plow through parentheses to get the first nested -// non-ParenExpr expr. -static inline Expr* IgnoreParen(Expr* E) { - while (ParenExpr* P = dyn_cast<ParenExpr>(E)) - E = P->getSubExpr(); - - return E; -} - -// Utility method to plow through parenthesis and casts. -static inline Expr* IgnoreParenCasts(Expr* E) { - while(true) { - if (ParenExpr* P = dyn_cast<ParenExpr>(E)) - E = P->getSubExpr(); - else if (CastExpr* P = dyn_cast<CastExpr>(E)) - E = P->getSubExpr(); - else if (ImplicitCastExpr* P = dyn_cast<ImplicitCastExpr>(E)) - E = P->getSubExpr(); - else - break; - } - - return E; -} - -// Utility method to determine if a CallExpr is a call to a builtin. -static inline bool isCallBuiltin(CallExpr* cexp) { - Expr* sub = IgnoreParenCasts(cexp->getCallee()); - - if (DeclRefExpr* E = dyn_cast<DeclRefExpr>(sub)) - if (E->getDecl()->getIdentifier()->getBuiltinID() > 0) - return true; - - return false; -} - inline QualType Sema::CheckCompareOperands( // C99 6.5.8 Expr *&lex, Expr *&rex, SourceLocation loc, bool isRelational) { @@ -1277,38 +1242,9 @@ inline QualType Sema::CheckCompareOperands( // C99 6.5.8 return Context.IntTy; } else { // Check for comparisons of floating point operands using != and ==. - // Issue a warning if these are no self-comparisons, as they are not likely - // to do what the programmer intended. if (lType->isFloatingType()) { assert (rType->isFloatingType()); - - // Special case: check for x == x (which is OK). - bool EmitWarning = true; - - Expr* LeftExprSansParen = IgnoreParen(lex); - Expr* RightExprSansParen = IgnoreParen(rex); - - // Look for x == x. Do not emit warnings for such cases. - if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen)) - if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RightExprSansParen)) - if (DRL->getDecl() == DRR->getDecl()) - EmitWarning = false; - - // Check for comparisons with builtin types. - if (EmitWarning) - if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen)) - if (isCallBuiltin(CL)) - EmitWarning = false; - - if (EmitWarning) - if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen)) - if (isCallBuiltin(CR)) - EmitWarning = false; - - // Emit the diagnostic. - if (EmitWarning) - Diag(loc, diag::warn_floatingpoint_eq, - lex->getSourceRange(),rex->getSourceRange()); + CheckFloatComparison(loc,lex,rex); } if (lType->isArithmeticType() && rType->isArithmeticType()) diff --git a/clang/Sema/SemaUtil.h b/clang/Sema/SemaUtil.h new file mode 100644 index 00000000000..2932862e91f --- /dev/null +++ b/clang/Sema/SemaUtil.h @@ -0,0 +1,60 @@ +//===--- SemaUtil.h - Utility functions for semantic analysis -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Ted Kremenek and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a few static inline functions that are useful for +// performing semantic analysis. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_UTIL_H +#define LLVM_CLANG_SEMA_UTIL_H + +#include "clang/AST/Expr.h" + +namespace clang { + +/// Utility method to plow through parentheses to get the first nested +/// non-ParenExpr expr. +static inline Expr* IgnoreParen(Expr* E) { + while (ParenExpr* P = dyn_cast<ParenExpr>(E)) + E = P->getSubExpr(); + + return E; +} + +/// Utility method to plow through parenthesis and casts. +static inline Expr* IgnoreParenCasts(Expr* E) { + while(true) { + if (ParenExpr* P = dyn_cast<ParenExpr>(E)) + E = P->getSubExpr(); + else if (CastExpr* P = dyn_cast<CastExpr>(E)) + E = P->getSubExpr(); + else if (ImplicitCastExpr* P = dyn_cast<ImplicitCastExpr>(E)) + E = P->getSubExpr(); + else + break; + } + + return E; +} + +/// Utility method to determine if a CallExpr is a call to a builtin. +static inline bool isCallBuiltin(CallExpr* cexp) { + Expr* sub = IgnoreParenCasts(cexp->getCallee()); + + if (DeclRefExpr* E = dyn_cast<DeclRefExpr>(sub)) + if (E->getDecl()->getIdentifier()->getBuiltinID() > 0) + return true; + + return false; +} + +} // end namespace clang + +#endif |