| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 1 | //===--- SemaChecking.cpp - Extra Semantic Checking -----------------------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
| Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 10 | //  This file implements extra semantic analysis beyond what is enforced | 
| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 11 | //  by the C type system. | 
 | 12 | // | 
 | 13 | //===----------------------------------------------------------------------===// | 
 | 14 |  | 
| John McCall | 5f8d604 | 2011-08-27 01:09:30 +0000 | [diff] [blame] | 15 | #include "clang/Sema/Initialization.h" | 
| Douglas Gregor | e737f50 | 2010-08-12 20:07:10 +0000 | [diff] [blame] | 16 | #include "clang/Sema/Sema.h" | 
| John McCall | 2d88708 | 2010-08-25 22:03:47 +0000 | [diff] [blame] | 17 | #include "clang/Sema/SemaInternal.h" | 
| Eli Friedman | 276b061 | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 18 | #include "clang/Sema/Initialization.h" | 
| John McCall | 781472f | 2010-08-25 08:40:02 +0000 | [diff] [blame] | 19 | #include "clang/Sema/ScopeInfo.h" | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 20 | #include "clang/Analysis/Analyses/FormatString.h" | 
| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 21 | #include "clang/AST/ASTContext.h" | 
| Ken Dyck | 199c3d6 | 2010-01-11 17:06:35 +0000 | [diff] [blame] | 22 | #include "clang/AST/CharUnits.h" | 
| John McCall | 384aff8 | 2010-08-25 07:42:41 +0000 | [diff] [blame] | 23 | #include "clang/AST/DeclCXX.h" | 
| Daniel Dunbar | c4a1dea | 2008-08-11 05:35:13 +0000 | [diff] [blame] | 24 | #include "clang/AST/DeclObjC.h" | 
| Ted Kremenek | 2324512 | 2007-08-20 16:18:38 +0000 | [diff] [blame] | 25 | #include "clang/AST/ExprCXX.h" | 
| Ted Kremenek | 7ff22b2 | 2008-06-16 18:00:42 +0000 | [diff] [blame] | 26 | #include "clang/AST/ExprObjC.h" | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 27 | #include "clang/AST/EvaluatedExprVisitor.h" | 
| Mike Stump | f8c4921 | 2010-01-21 03:59:47 +0000 | [diff] [blame] | 28 | #include "clang/AST/DeclObjC.h" | 
 | 29 | #include "clang/AST/StmtCXX.h" | 
 | 30 | #include "clang/AST/StmtObjC.h" | 
| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 31 | #include "clang/Lex/Preprocessor.h" | 
| Mike Stump | f8c4921 | 2010-01-21 03:59:47 +0000 | [diff] [blame] | 32 | #include "llvm/ADT/BitVector.h" | 
 | 33 | #include "llvm/ADT/STLExtras.h" | 
| Tom Care | 3bfc5f4 | 2010-06-09 04:11:11 +0000 | [diff] [blame] | 34 | #include "llvm/Support/raw_ostream.h" | 
| Eric Christopher | 691ebc3 | 2010-04-17 02:26:23 +0000 | [diff] [blame] | 35 | #include "clang/Basic/TargetBuiltins.h" | 
| Nate Begeman | 26a3142 | 2010-06-08 02:47:44 +0000 | [diff] [blame] | 36 | #include "clang/Basic/TargetInfo.h" | 
| Fariborz Jahanian | 7da7102 | 2010-09-07 19:38:13 +0000 | [diff] [blame] | 37 | #include "clang/Basic/ConvertUTF.h" | 
| Zhongxing Xu | a1f3dba | 2009-05-20 01:55:10 +0000 | [diff] [blame] | 38 | #include <limits> | 
| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 39 | using namespace clang; | 
| John McCall | 781472f | 2010-08-25 08:40:02 +0000 | [diff] [blame] | 40 | using namespace sema; | 
| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 41 |  | 
| Chris Lattner | 6080008 | 2009-02-18 17:49:48 +0000 | [diff] [blame] | 42 | SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, | 
 | 43 |                                                     unsigned ByteNo) const { | 
| Chris Lattner | 08f92e3 | 2010-11-17 07:37:15 +0000 | [diff] [blame] | 44 |   return SL->getLocationOfByte(ByteNo, PP.getSourceManager(), | 
 | 45 |                                PP.getLangOptions(), PP.getTargetInfo()); | 
| Chris Lattner | 6080008 | 2009-02-18 17:49:48 +0000 | [diff] [blame] | 46 | } | 
| Chris Lattner | 08f92e3 | 2010-11-17 07:37:15 +0000 | [diff] [blame] | 47 |    | 
| Chris Lattner | 6080008 | 2009-02-18 17:49:48 +0000 | [diff] [blame] | 48 |  | 
| Ryan Flynn | 4403a5e | 2009-08-06 03:00:50 +0000 | [diff] [blame] | 49 | /// CheckablePrintfAttr - does a function call have a "printf" attribute | 
 | 50 | /// and arguments that merit checking? | 
 | 51 | bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) { | 
 | 52 |   if (Format->getType() == "printf") return true; | 
 | 53 |   if (Format->getType() == "printf0") { | 
 | 54 |     // printf0 allows null "format" string; if so don't check format/args | 
 | 55 |     unsigned format_idx = Format->getFormatIdx() - 1; | 
| Sebastian Redl | 4a2614e | 2009-11-17 18:02:24 +0000 | [diff] [blame] | 56 |     // Does the index refer to the implicit object argument? | 
 | 57 |     if (isa<CXXMemberCallExpr>(TheCall)) { | 
 | 58 |       if (format_idx == 0) | 
 | 59 |         return false; | 
 | 60 |       --format_idx; | 
 | 61 |     } | 
| Ryan Flynn | 4403a5e | 2009-08-06 03:00:50 +0000 | [diff] [blame] | 62 |     if (format_idx < TheCall->getNumArgs()) { | 
 | 63 |       Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts(); | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 64 |       if (!Format->isNullPointerConstant(Context, | 
 | 65 |                                          Expr::NPC_ValueDependentIsNull)) | 
| Ryan Flynn | 4403a5e | 2009-08-06 03:00:50 +0000 | [diff] [blame] | 66 |         return true; | 
 | 67 |     } | 
 | 68 |   } | 
 | 69 |   return false; | 
 | 70 | } | 
| Chris Lattner | 6080008 | 2009-02-18 17:49:48 +0000 | [diff] [blame] | 71 |  | 
| John McCall | 8e10f3b | 2011-02-26 05:39:39 +0000 | [diff] [blame] | 72 | /// Checks that a call expression's argument count is the desired number. | 
 | 73 | /// This is useful when doing custom type-checking.  Returns true on error. | 
 | 74 | static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) { | 
 | 75 |   unsigned argCount = call->getNumArgs(); | 
 | 76 |   if (argCount == desiredArgCount) return false; | 
 | 77 |  | 
 | 78 |   if (argCount < desiredArgCount) | 
 | 79 |     return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args) | 
 | 80 |         << 0 /*function call*/ << desiredArgCount << argCount | 
 | 81 |         << call->getSourceRange(); | 
 | 82 |  | 
 | 83 |   // Highlight all the excess arguments. | 
 | 84 |   SourceRange range(call->getArg(desiredArgCount)->getLocStart(), | 
 | 85 |                     call->getArg(argCount - 1)->getLocEnd()); | 
 | 86 |      | 
 | 87 |   return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args) | 
 | 88 |     << 0 /*function call*/ << desiredArgCount << argCount | 
 | 89 |     << call->getArg(1)->getSourceRange(); | 
 | 90 | } | 
 | 91 |  | 
| Julien Lerouge | 77f68bb | 2011-09-09 22:41:49 +0000 | [diff] [blame] | 92 | /// CheckBuiltinAnnotationString - Checks that string argument to the builtin | 
 | 93 | /// annotation is a non wide string literal. | 
 | 94 | static bool CheckBuiltinAnnotationString(Sema &S, Expr *Arg) { | 
 | 95 |   Arg = Arg->IgnoreParenCasts(); | 
 | 96 |   StringLiteral *Literal = dyn_cast<StringLiteral>(Arg); | 
 | 97 |   if (!Literal || !Literal->isAscii()) { | 
 | 98 |     S.Diag(Arg->getLocStart(), diag::err_builtin_annotation_not_string_constant) | 
 | 99 |       << Arg->getSourceRange(); | 
 | 100 |     return true; | 
 | 101 |   } | 
 | 102 |   return false; | 
 | 103 | } | 
 | 104 |  | 
| John McCall | 60d7b3a | 2010-08-24 06:29:42 +0000 | [diff] [blame] | 105 | ExprResult | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 106 | Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { | 
| John McCall | 60d7b3a | 2010-08-24 06:29:42 +0000 | [diff] [blame] | 107 |   ExprResult TheCallResult(Owned(TheCall)); | 
| Douglas Gregor | 2def483 | 2008-11-17 20:34:05 +0000 | [diff] [blame] | 108 |  | 
| Chris Lattner | 946928f | 2010-10-01 23:23:24 +0000 | [diff] [blame] | 109 |   // Find out if any arguments are required to be integer constant expressions. | 
 | 110 |   unsigned ICEArguments = 0; | 
 | 111 |   ASTContext::GetBuiltinTypeError Error; | 
 | 112 |   Context.GetBuiltinType(BuiltinID, Error, &ICEArguments); | 
 | 113 |   if (Error != ASTContext::GE_None) | 
 | 114 |     ICEArguments = 0;  // Don't diagnose previously diagnosed errors. | 
 | 115 |    | 
 | 116 |   // If any arguments are required to be ICE's, check and diagnose. | 
 | 117 |   for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) { | 
 | 118 |     // Skip arguments not required to be ICE's. | 
 | 119 |     if ((ICEArguments & (1 << ArgNo)) == 0) continue; | 
 | 120 |      | 
 | 121 |     llvm::APSInt Result; | 
 | 122 |     if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) | 
 | 123 |       return true; | 
 | 124 |     ICEArguments &= ~(1 << ArgNo); | 
 | 125 |   } | 
 | 126 |    | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 127 |   switch (BuiltinID) { | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 128 |   case Builtin::BI__builtin___CFStringMakeConstantString: | 
| Chris Lattner | 925e60d | 2007-12-28 05:29:59 +0000 | [diff] [blame] | 129 |     assert(TheCall->getNumArgs() == 1 && | 
| Chris Lattner | 1b9a079 | 2007-12-20 00:26:33 +0000 | [diff] [blame] | 130 |            "Wrong # arguments to builtin CFStringMakeConstantString"); | 
| Chris Lattner | 6903981 | 2009-02-18 06:01:06 +0000 | [diff] [blame] | 131 |     if (CheckObjCString(TheCall->getArg(0))) | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 132 |       return ExprError(); | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 133 |     break; | 
| Ted Kremenek | 49ff7a1 | 2008-07-09 17:58:53 +0000 | [diff] [blame] | 134 |   case Builtin::BI__builtin_stdarg_start: | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 135 |   case Builtin::BI__builtin_va_start: | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 136 |     if (SemaBuiltinVAStart(TheCall)) | 
 | 137 |       return ExprError(); | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 138 |     break; | 
| Chris Lattner | 1b9a079 | 2007-12-20 00:26:33 +0000 | [diff] [blame] | 139 |   case Builtin::BI__builtin_isgreater: | 
 | 140 |   case Builtin::BI__builtin_isgreaterequal: | 
 | 141 |   case Builtin::BI__builtin_isless: | 
 | 142 |   case Builtin::BI__builtin_islessequal: | 
 | 143 |   case Builtin::BI__builtin_islessgreater: | 
 | 144 |   case Builtin::BI__builtin_isunordered: | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 145 |     if (SemaBuiltinUnorderedCompare(TheCall)) | 
 | 146 |       return ExprError(); | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 147 |     break; | 
| Benjamin Kramer | e771a7a | 2010-02-15 22:42:31 +0000 | [diff] [blame] | 148 |   case Builtin::BI__builtin_fpclassify: | 
 | 149 |     if (SemaBuiltinFPClassification(TheCall, 6)) | 
 | 150 |       return ExprError(); | 
 | 151 |     break; | 
| Eli Friedman | 9ac6f62 | 2009-08-31 20:06:00 +0000 | [diff] [blame] | 152 |   case Builtin::BI__builtin_isfinite: | 
 | 153 |   case Builtin::BI__builtin_isinf: | 
 | 154 |   case Builtin::BI__builtin_isinf_sign: | 
 | 155 |   case Builtin::BI__builtin_isnan: | 
 | 156 |   case Builtin::BI__builtin_isnormal: | 
| Benjamin Kramer | 3b1e26b | 2010-02-16 10:07:31 +0000 | [diff] [blame] | 157 |     if (SemaBuiltinFPClassification(TheCall, 1)) | 
| Eli Friedman | 9ac6f62 | 2009-08-31 20:06:00 +0000 | [diff] [blame] | 158 |       return ExprError(); | 
 | 159 |     break; | 
| Eli Friedman | d38617c | 2008-05-14 19:38:39 +0000 | [diff] [blame] | 160 |   case Builtin::BI__builtin_shufflevector: | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 161 |     return SemaBuiltinShuffleVector(TheCall); | 
 | 162 |     // TheCall will be freed by the smart pointer here, but that's fine, since | 
 | 163 |     // SemaBuiltinShuffleVector guts it, but then doesn't release it. | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 164 |   case Builtin::BI__builtin_prefetch: | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 165 |     if (SemaBuiltinPrefetch(TheCall)) | 
 | 166 |       return ExprError(); | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 167 |     break; | 
| Daniel Dunbar | d5f8a4f | 2008-09-03 21:13:56 +0000 | [diff] [blame] | 168 |   case Builtin::BI__builtin_object_size: | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 169 |     if (SemaBuiltinObjectSize(TheCall)) | 
 | 170 |       return ExprError(); | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 171 |     break; | 
| Eli Friedman | d875fed | 2009-05-03 04:46:36 +0000 | [diff] [blame] | 172 |   case Builtin::BI__builtin_longjmp: | 
 | 173 |     if (SemaBuiltinLongjmp(TheCall)) | 
 | 174 |       return ExprError(); | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 175 |     break; | 
| John McCall | 8e10f3b | 2011-02-26 05:39:39 +0000 | [diff] [blame] | 176 |  | 
 | 177 |   case Builtin::BI__builtin_classify_type: | 
 | 178 |     if (checkArgCount(*this, TheCall, 1)) return true; | 
 | 179 |     TheCall->setType(Context.IntTy); | 
 | 180 |     break; | 
| Chris Lattner | 75c29a0 | 2010-10-12 17:47:42 +0000 | [diff] [blame] | 181 |   case Builtin::BI__builtin_constant_p: | 
| John McCall | 8e10f3b | 2011-02-26 05:39:39 +0000 | [diff] [blame] | 182 |     if (checkArgCount(*this, TheCall, 1)) return true; | 
 | 183 |     TheCall->setType(Context.IntTy); | 
| Chris Lattner | 75c29a0 | 2010-10-12 17:47:42 +0000 | [diff] [blame] | 184 |     break; | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 185 |   case Builtin::BI__sync_fetch_and_add: | 
 | 186 |   case Builtin::BI__sync_fetch_and_sub: | 
 | 187 |   case Builtin::BI__sync_fetch_and_or: | 
 | 188 |   case Builtin::BI__sync_fetch_and_and: | 
 | 189 |   case Builtin::BI__sync_fetch_and_xor: | 
 | 190 |   case Builtin::BI__sync_add_and_fetch: | 
 | 191 |   case Builtin::BI__sync_sub_and_fetch: | 
 | 192 |   case Builtin::BI__sync_and_and_fetch: | 
 | 193 |   case Builtin::BI__sync_or_and_fetch: | 
 | 194 |   case Builtin::BI__sync_xor_and_fetch: | 
 | 195 |   case Builtin::BI__sync_val_compare_and_swap: | 
 | 196 |   case Builtin::BI__sync_bool_compare_and_swap: | 
 | 197 |   case Builtin::BI__sync_lock_test_and_set: | 
 | 198 |   case Builtin::BI__sync_lock_release: | 
| Chris Lattner | 23aa9c8 | 2011-04-09 03:57:26 +0000 | [diff] [blame] | 199 |   case Builtin::BI__sync_swap: | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 200 |     return SemaBuiltinAtomicOverloaded(move(TheCallResult)); | 
| Eli Friedman | 276b061 | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 201 |   case Builtin::BI__atomic_load: | 
 | 202 |     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Load); | 
 | 203 |   case Builtin::BI__atomic_store: | 
 | 204 |     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Store); | 
 | 205 |   case Builtin::BI__atomic_exchange: | 
 | 206 |     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Xchg); | 
 | 207 |   case Builtin::BI__atomic_compare_exchange_strong: | 
 | 208 |     return SemaAtomicOpsOverloaded(move(TheCallResult), | 
 | 209 |                                    AtomicExpr::CmpXchgStrong); | 
 | 210 |   case Builtin::BI__atomic_compare_exchange_weak: | 
 | 211 |     return SemaAtomicOpsOverloaded(move(TheCallResult), | 
 | 212 |                                    AtomicExpr::CmpXchgWeak); | 
 | 213 |   case Builtin::BI__atomic_fetch_add: | 
 | 214 |     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Add); | 
 | 215 |   case Builtin::BI__atomic_fetch_sub: | 
 | 216 |     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Sub); | 
 | 217 |   case Builtin::BI__atomic_fetch_and: | 
 | 218 |     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::And); | 
 | 219 |   case Builtin::BI__atomic_fetch_or: | 
 | 220 |     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Or); | 
 | 221 |   case Builtin::BI__atomic_fetch_xor: | 
 | 222 |     return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Xor); | 
| Julien Lerouge | 77f68bb | 2011-09-09 22:41:49 +0000 | [diff] [blame] | 223 |   case Builtin::BI__builtin_annotation: | 
 | 224 |     if (CheckBuiltinAnnotationString(*this, TheCall->getArg(1))) | 
 | 225 |       return ExprError(); | 
 | 226 |     break; | 
| Nate Begeman | 26a3142 | 2010-06-08 02:47:44 +0000 | [diff] [blame] | 227 |   } | 
 | 228 |    | 
 | 229 |   // Since the target specific builtins for each arch overlap, only check those | 
 | 230 |   // of the arch we are compiling for. | 
 | 231 |   if (BuiltinID >= Builtin::FirstTSBuiltin) { | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 232 |     switch (Context.getTargetInfo().getTriple().getArch()) { | 
| Nate Begeman | 26a3142 | 2010-06-08 02:47:44 +0000 | [diff] [blame] | 233 |       case llvm::Triple::arm: | 
 | 234 |       case llvm::Triple::thumb: | 
 | 235 |         if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall)) | 
 | 236 |           return ExprError(); | 
 | 237 |         break; | 
| Nate Begeman | 26a3142 | 2010-06-08 02:47:44 +0000 | [diff] [blame] | 238 |       default: | 
 | 239 |         break; | 
 | 240 |     } | 
 | 241 |   } | 
 | 242 |  | 
 | 243 |   return move(TheCallResult); | 
 | 244 | } | 
 | 245 |  | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 246 | // Get the valid immediate range for the specified NEON type code. | 
 | 247 | static unsigned RFT(unsigned t, bool shift = false) { | 
 | 248 |   bool quad = t & 0x10; | 
 | 249 |    | 
 | 250 |   switch (t & 0x7) { | 
 | 251 |     case 0: // i8 | 
| Nate Begeman | d69ec16 | 2010-06-17 02:26:59 +0000 | [diff] [blame] | 252 |       return shift ? 7 : (8 << (int)quad) - 1; | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 253 |     case 1: // i16 | 
| Nate Begeman | d69ec16 | 2010-06-17 02:26:59 +0000 | [diff] [blame] | 254 |       return shift ? 15 : (4 << (int)quad) - 1; | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 255 |     case 2: // i32 | 
| Nate Begeman | d69ec16 | 2010-06-17 02:26:59 +0000 | [diff] [blame] | 256 |       return shift ? 31 : (2 << (int)quad) - 1; | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 257 |     case 3: // i64 | 
| Nate Begeman | d69ec16 | 2010-06-17 02:26:59 +0000 | [diff] [blame] | 258 |       return shift ? 63 : (1 << (int)quad) - 1; | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 259 |     case 4: // f32 | 
 | 260 |       assert(!shift && "cannot shift float types!"); | 
| Nate Begeman | d69ec16 | 2010-06-17 02:26:59 +0000 | [diff] [blame] | 261 |       return (2 << (int)quad) - 1; | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 262 |     case 5: // poly8 | 
| Bob Wilson | 42499f9 | 2010-12-10 19:45:06 +0000 | [diff] [blame] | 263 |       return shift ? 7 : (8 << (int)quad) - 1; | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 264 |     case 6: // poly16 | 
| Bob Wilson | 42499f9 | 2010-12-10 19:45:06 +0000 | [diff] [blame] | 265 |       return shift ? 15 : (4 << (int)quad) - 1; | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 266 |     case 7: // float16 | 
 | 267 |       assert(!shift && "cannot shift float types!"); | 
| Nate Begeman | d69ec16 | 2010-06-17 02:26:59 +0000 | [diff] [blame] | 268 |       return (4 << (int)quad) - 1; | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 269 |   } | 
 | 270 |   return 0; | 
 | 271 | } | 
 | 272 |  | 
| Nate Begeman | 26a3142 | 2010-06-08 02:47:44 +0000 | [diff] [blame] | 273 | bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { | 
| Nate Begeman | 1c2a88c | 2010-06-09 01:10:23 +0000 | [diff] [blame] | 274 |   llvm::APSInt Result; | 
 | 275 |  | 
| Nate Begeman | 0d15c53 | 2010-06-13 04:47:52 +0000 | [diff] [blame] | 276 |   unsigned mask = 0; | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 277 |   unsigned TV = 0; | 
| Nate Begeman | 1c2a88c | 2010-06-09 01:10:23 +0000 | [diff] [blame] | 278 |   switch (BuiltinID) { | 
| Nate Begeman | a23326b | 2010-06-17 04:17:01 +0000 | [diff] [blame] | 279 | #define GET_NEON_OVERLOAD_CHECK | 
 | 280 | #include "clang/Basic/arm_neon.inc" | 
 | 281 | #undef GET_NEON_OVERLOAD_CHECK | 
| Nate Begeman | 1c2a88c | 2010-06-09 01:10:23 +0000 | [diff] [blame] | 282 |   } | 
 | 283 |    | 
| Nate Begeman | 0d15c53 | 2010-06-13 04:47:52 +0000 | [diff] [blame] | 284 |   // For NEON intrinsics which are overloaded on vector element type, validate | 
 | 285 |   // the immediate which specifies which variant to emit. | 
 | 286 |   if (mask) { | 
 | 287 |     unsigned ArgNo = TheCall->getNumArgs()-1; | 
 | 288 |     if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) | 
 | 289 |       return true; | 
 | 290 |      | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 291 |     TV = Result.getLimitedValue(32); | 
 | 292 |     if ((TV > 31) || (mask & (1 << TV)) == 0) | 
| Nate Begeman | 0d15c53 | 2010-06-13 04:47:52 +0000 | [diff] [blame] | 293 |       return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code) | 
 | 294 |         << TheCall->getArg(ArgNo)->getSourceRange(); | 
 | 295 |   } | 
| Nate Begeman | 1c2a88c | 2010-06-09 01:10:23 +0000 | [diff] [blame] | 296 |    | 
| Nate Begeman | 0d15c53 | 2010-06-13 04:47:52 +0000 | [diff] [blame] | 297 |   // For NEON intrinsics which take an immediate value as part of the  | 
 | 298 |   // instruction, range check them here. | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 299 |   unsigned i = 0, l = 0, u = 0; | 
| Nate Begeman | 0d15c53 | 2010-06-13 04:47:52 +0000 | [diff] [blame] | 300 |   switch (BuiltinID) { | 
 | 301 |   default: return false; | 
| Nate Begeman | bb37f50 | 2010-07-29 22:48:34 +0000 | [diff] [blame] | 302 |   case ARM::BI__builtin_arm_ssat: i = 1; l = 1; u = 31; break; | 
 | 303 |   case ARM::BI__builtin_arm_usat: i = 1; u = 31; break; | 
| Nate Begeman | 99c40bb | 2010-08-03 21:32:34 +0000 | [diff] [blame] | 304 |   case ARM::BI__builtin_arm_vcvtr_f: | 
 | 305 |   case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break; | 
| Nate Begeman | a23326b | 2010-06-17 04:17:01 +0000 | [diff] [blame] | 306 | #define GET_NEON_IMMEDIATE_CHECK | 
 | 307 | #include "clang/Basic/arm_neon.inc" | 
 | 308 | #undef GET_NEON_IMMEDIATE_CHECK | 
| Nate Begeman | 0d15c53 | 2010-06-13 04:47:52 +0000 | [diff] [blame] | 309 |   }; | 
 | 310 |  | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 311 |   // Check that the immediate argument is actually a constant. | 
| Nate Begeman | 0d15c53 | 2010-06-13 04:47:52 +0000 | [diff] [blame] | 312 |   if (SemaBuiltinConstantArg(TheCall, i, Result)) | 
 | 313 |     return true; | 
 | 314 |  | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 315 |   // Range check against the upper/lower values for this isntruction. | 
| Nate Begeman | 0d15c53 | 2010-06-13 04:47:52 +0000 | [diff] [blame] | 316 |   unsigned Val = Result.getZExtValue(); | 
| Nate Begeman | 61eecf5 | 2010-06-14 05:21:25 +0000 | [diff] [blame] | 317 |   if (Val < l || Val > (u + l)) | 
| Nate Begeman | 0d15c53 | 2010-06-13 04:47:52 +0000 | [diff] [blame] | 318 |     return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) | 
| Benjamin Kramer | 476d8b8 | 2010-08-11 14:47:12 +0000 | [diff] [blame] | 319 |       << l << u+l << TheCall->getArg(i)->getSourceRange(); | 
| Nate Begeman | 0d15c53 | 2010-06-13 04:47:52 +0000 | [diff] [blame] | 320 |  | 
| Nate Begeman | 99c40bb | 2010-08-03 21:32:34 +0000 | [diff] [blame] | 321 |   // FIXME: VFP Intrinsics should error if VFP not present. | 
| Nate Begeman | 26a3142 | 2010-06-08 02:47:44 +0000 | [diff] [blame] | 322 |   return false; | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 323 | } | 
| Daniel Dunbar | de45428 | 2008-10-02 18:44:07 +0000 | [diff] [blame] | 324 |  | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 325 | /// CheckFunctionCall - Check a direct function call for various correctness | 
 | 326 | /// and safety properties not strictly enforced by the C type system. | 
 | 327 | bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { | 
 | 328 |   // Get the IdentifierInfo* for the called function. | 
 | 329 |   IdentifierInfo *FnInfo = FDecl->getIdentifier(); | 
 | 330 |  | 
 | 331 |   // None of the checks below are needed for functions that don't have | 
 | 332 |   // simple names (e.g., C++ conversion functions). | 
 | 333 |   if (!FnInfo) | 
 | 334 |     return false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 335 |  | 
| Daniel Dunbar | de45428 | 2008-10-02 18:44:07 +0000 | [diff] [blame] | 336 |   // FIXME: This mechanism should be abstracted to be less fragile and | 
 | 337 |   // more efficient. For example, just map function ids to custom | 
 | 338 |   // handlers. | 
 | 339 |  | 
| Ted Kremenek | c82faca | 2010-09-09 04:33:05 +0000 | [diff] [blame] | 340 |   // Printf and scanf checking. | 
 | 341 |   for (specific_attr_iterator<FormatAttr> | 
 | 342 |          i = FDecl->specific_attr_begin<FormatAttr>(), | 
 | 343 |          e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) { | 
 | 344 |  | 
 | 345 |     const FormatAttr *Format = *i; | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 346 |     const bool b = Format->getType() == "scanf"; | 
 | 347 |     if (b || CheckablePrintfAttr(Format, TheCall)) { | 
| Ted Kremenek | 3d692df | 2009-02-27 17:58:43 +0000 | [diff] [blame] | 348 |       bool HasVAListArg = Format->getFirstArg() == 0; | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 349 |       CheckPrintfScanfArguments(TheCall, HasVAListArg, | 
 | 350 |                                 Format->getFormatIdx() - 1, | 
 | 351 |                                 HasVAListArg ? 0 : Format->getFirstArg() - 1, | 
 | 352 |                                 !b); | 
| Douglas Gregor | 3c385e5 | 2009-02-14 18:57:46 +0000 | [diff] [blame] | 353 |     } | 
| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 354 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 355 |  | 
| Ted Kremenek | c82faca | 2010-09-09 04:33:05 +0000 | [diff] [blame] | 356 |   for (specific_attr_iterator<NonNullAttr> | 
 | 357 |          i = FDecl->specific_attr_begin<NonNullAttr>(), | 
 | 358 |          e = FDecl->specific_attr_end<NonNullAttr>(); i != e; ++i) { | 
| Nick Lewycky | 909a70d | 2011-03-25 01:44:32 +0000 | [diff] [blame] | 359 |     CheckNonNullArguments(*i, TheCall->getArgs(), | 
 | 360 |                           TheCall->getCallee()->getLocStart()); | 
| Ted Kremenek | c82faca | 2010-09-09 04:33:05 +0000 | [diff] [blame] | 361 |   } | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 362 |  | 
| Ted Kremenek | bd5da9d | 2011-08-18 20:55:45 +0000 | [diff] [blame] | 363 |   // Builtin handling | 
| Douglas Gregor | 707a23e | 2011-06-16 17:56:04 +0000 | [diff] [blame] | 364 |   int CMF = -1; | 
 | 365 |   switch (FDecl->getBuiltinID()) { | 
 | 366 |   case Builtin::BI__builtin_memset: | 
 | 367 |   case Builtin::BI__builtin___memset_chk: | 
 | 368 |   case Builtin::BImemset: | 
 | 369 |     CMF = CMF_Memset; | 
 | 370 |     break; | 
 | 371 |      | 
 | 372 |   case Builtin::BI__builtin_memcpy: | 
 | 373 |   case Builtin::BI__builtin___memcpy_chk: | 
 | 374 |   case Builtin::BImemcpy: | 
 | 375 |     CMF = CMF_Memcpy; | 
 | 376 |     break; | 
 | 377 |      | 
 | 378 |   case Builtin::BI__builtin_memmove: | 
 | 379 |   case Builtin::BI__builtin___memmove_chk: | 
 | 380 |   case Builtin::BImemmove: | 
 | 381 |     CMF = CMF_Memmove; | 
 | 382 |     break; | 
| Ted Kremenek | bd5da9d | 2011-08-18 20:55:45 +0000 | [diff] [blame] | 383 |  | 
 | 384 |   case Builtin::BIstrlcpy: | 
 | 385 |   case Builtin::BIstrlcat: | 
 | 386 |     CheckStrlcpycatArguments(TheCall, FnInfo); | 
 | 387 |     break; | 
| Douglas Gregor | 707a23e | 2011-06-16 17:56:04 +0000 | [diff] [blame] | 388 |      | 
| Matt Beaumont-Gay | cc2f30c | 2011-08-05 00:22:34 +0000 | [diff] [blame] | 389 |   case Builtin::BI__builtin_memcmp: | 
 | 390 |     CMF = CMF_Memcmp; | 
 | 391 |     break; | 
 | 392 |      | 
| Nico Weber | cda5782 | 2011-10-13 22:30:23 +0000 | [diff] [blame] | 393 |   case Builtin::BI__builtin_strncpy: | 
 | 394 |   case Builtin::BI__builtin___strncpy_chk: | 
 | 395 |   case Builtin::BIstrncpy: | 
 | 396 |     CMF = CMF_Strncpy; | 
 | 397 |     break; | 
 | 398 |  | 
 | 399 |   case Builtin::BI__builtin_strncmp: | 
 | 400 |     CMF = CMF_Strncmp; | 
 | 401 |     break; | 
 | 402 |  | 
 | 403 |   case Builtin::BI__builtin_strncasecmp: | 
 | 404 |     CMF = CMF_Strncasecmp; | 
 | 405 |     break; | 
 | 406 |  | 
 | 407 |   case Builtin::BI__builtin_strncat: | 
 | 408 |   case Builtin::BIstrncat: | 
 | 409 |     CMF = CMF_Strncat; | 
 | 410 |     break; | 
 | 411 |  | 
 | 412 |   case Builtin::BI__builtin_strndup: | 
 | 413 |   case Builtin::BIstrndup: | 
 | 414 |     CMF = CMF_Strndup; | 
 | 415 |     break; | 
 | 416 |  | 
| Douglas Gregor | 707a23e | 2011-06-16 17:56:04 +0000 | [diff] [blame] | 417 |   default: | 
 | 418 |     if (FDecl->getLinkage() == ExternalLinkage && | 
 | 419 |         (!getLangOptions().CPlusPlus || FDecl->isExternC())) { | 
 | 420 |       if (FnInfo->isStr("memset")) | 
 | 421 |         CMF = CMF_Memset; | 
 | 422 |       else if (FnInfo->isStr("memcpy")) | 
 | 423 |         CMF = CMF_Memcpy; | 
 | 424 |       else if (FnInfo->isStr("memmove")) | 
 | 425 |         CMF = CMF_Memmove; | 
| Matt Beaumont-Gay | cc2f30c | 2011-08-05 00:22:34 +0000 | [diff] [blame] | 426 |       else if (FnInfo->isStr("memcmp")) | 
 | 427 |         CMF = CMF_Memcmp; | 
| Nico Weber | cda5782 | 2011-10-13 22:30:23 +0000 | [diff] [blame] | 428 |       else if (FnInfo->isStr("strncpy")) | 
 | 429 |         CMF = CMF_Strncpy; | 
 | 430 |       else if (FnInfo->isStr("strncmp")) | 
 | 431 |         CMF = CMF_Strncmp; | 
 | 432 |       else if (FnInfo->isStr("strncasecmp")) | 
 | 433 |         CMF = CMF_Strncasecmp; | 
 | 434 |       else if (FnInfo->isStr("strncat")) | 
 | 435 |         CMF = CMF_Strncat; | 
 | 436 |       else if (FnInfo->isStr("strndup")) | 
 | 437 |         CMF = CMF_Strndup; | 
| Douglas Gregor | 707a23e | 2011-06-16 17:56:04 +0000 | [diff] [blame] | 438 |     } | 
 | 439 |     break; | 
| Douglas Gregor | 06bc9eb | 2011-05-03 20:37:33 +0000 | [diff] [blame] | 440 |   } | 
| Douglas Gregor | 707a23e | 2011-06-16 17:56:04 +0000 | [diff] [blame] | 441 |     | 
| Ted Kremenek | bd5da9d | 2011-08-18 20:55:45 +0000 | [diff] [blame] | 442 |   // Memset/memcpy/memmove handling | 
| Douglas Gregor | 707a23e | 2011-06-16 17:56:04 +0000 | [diff] [blame] | 443 |   if (CMF != -1) | 
| Matt Beaumont-Gay | cc2f30c | 2011-08-05 00:22:34 +0000 | [diff] [blame] | 444 |     CheckMemaccessArguments(TheCall, CheckedMemoryFunction(CMF), FnInfo); | 
| Chandler Carruth | 7ccc95b | 2011-04-27 07:05:31 +0000 | [diff] [blame] | 445 |  | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 446 |   return false; | 
| Anders Carlsson | 71993dd | 2007-08-17 05:31:46 +0000 | [diff] [blame] | 447 | } | 
 | 448 |  | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 449 | bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { | 
| Fariborz Jahanian | 725165f | 2009-05-18 21:05:18 +0000 | [diff] [blame] | 450 |   // Printf checking. | 
| Argyrios Kyrtzidis | 40b598e | 2009-06-30 02:34:44 +0000 | [diff] [blame] | 451 |   const FormatAttr *Format = NDecl->getAttr<FormatAttr>(); | 
| Fariborz Jahanian | 725165f | 2009-05-18 21:05:18 +0000 | [diff] [blame] | 452 |   if (!Format) | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 453 |     return false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 454 |  | 
| Fariborz Jahanian | 725165f | 2009-05-18 21:05:18 +0000 | [diff] [blame] | 455 |   const VarDecl *V = dyn_cast<VarDecl>(NDecl); | 
 | 456 |   if (!V) | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 457 |     return false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 458 |  | 
| Fariborz Jahanian | 725165f | 2009-05-18 21:05:18 +0000 | [diff] [blame] | 459 |   QualType Ty = V->getType(); | 
 | 460 |   if (!Ty->isBlockPointerType()) | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 461 |     return false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 462 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 463 |   const bool b = Format->getType() == "scanf"; | 
 | 464 |   if (!b && !CheckablePrintfAttr(Format, TheCall)) | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 465 |     return false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 466 |  | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 467 |   bool HasVAListArg = Format->getFirstArg() == 0; | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 468 |   CheckPrintfScanfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1, | 
 | 469 |                             HasVAListArg ? 0 : Format->getFirstArg() - 1, !b); | 
| Anders Carlsson | d406bf0 | 2009-08-16 01:56:34 +0000 | [diff] [blame] | 470 |  | 
 | 471 |   return false; | 
| Fariborz Jahanian | 725165f | 2009-05-18 21:05:18 +0000 | [diff] [blame] | 472 | } | 
 | 473 |  | 
| Eli Friedman | 276b061 | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 474 | ExprResult | 
 | 475 | Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op) { | 
 | 476 |   CallExpr *TheCall = cast<CallExpr>(TheCallResult.get()); | 
 | 477 |   DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); | 
| Eli Friedman | 276b061 | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 478 |  | 
 | 479 |   // All these operations take one of the following four forms: | 
 | 480 |   // T   __atomic_load(_Atomic(T)*, int)                              (loads) | 
 | 481 |   // T*  __atomic_add(_Atomic(T*)*, ptrdiff_t, int)         (pointer add/sub) | 
 | 482 |   // int __atomic_compare_exchange_strong(_Atomic(T)*, T*, T, int, int) | 
 | 483 |   //                                                                (cmpxchg) | 
 | 484 |   // T   __atomic_exchange(_Atomic(T)*, T, int)             (everything else) | 
 | 485 |   // where T is an appropriate type, and the int paremeterss are for orderings. | 
 | 486 |   unsigned NumVals = 1; | 
 | 487 |   unsigned NumOrders = 1; | 
 | 488 |   if (Op == AtomicExpr::Load) { | 
 | 489 |     NumVals = 0; | 
 | 490 |   } else if (Op == AtomicExpr::CmpXchgWeak || Op == AtomicExpr::CmpXchgStrong) { | 
 | 491 |     NumVals = 2; | 
 | 492 |     NumOrders = 2; | 
 | 493 |   } | 
 | 494 |  | 
 | 495 |   if (TheCall->getNumArgs() < NumVals+NumOrders+1) { | 
 | 496 |     Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) | 
 | 497 |       << 0 << NumVals+NumOrders+1 << TheCall->getNumArgs() | 
 | 498 |       << TheCall->getCallee()->getSourceRange(); | 
 | 499 |     return ExprError(); | 
 | 500 |   } else if (TheCall->getNumArgs() > NumVals+NumOrders+1) { | 
 | 501 |     Diag(TheCall->getArg(NumVals+NumOrders+1)->getLocStart(), | 
 | 502 |          diag::err_typecheck_call_too_many_args) | 
 | 503 |       << 0 << NumVals+NumOrders+1 << TheCall->getNumArgs() | 
 | 504 |       << TheCall->getCallee()->getSourceRange(); | 
 | 505 |     return ExprError(); | 
 | 506 |   } | 
 | 507 |  | 
 | 508 |   // Inspect the first argument of the atomic operation.  This should always be | 
 | 509 |   // a pointer to an _Atomic type. | 
| Eli Friedman | dfa64ba | 2011-10-14 22:48:56 +0000 | [diff] [blame] | 510 |   Expr *Ptr = TheCall->getArg(0); | 
| Eli Friedman | 276b061 | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 511 |   Ptr = DefaultFunctionArrayLvalueConversion(Ptr).get(); | 
 | 512 |   const PointerType *pointerType = Ptr->getType()->getAs<PointerType>(); | 
 | 513 |   if (!pointerType) { | 
 | 514 |     Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic) | 
 | 515 |       << Ptr->getType() << Ptr->getSourceRange(); | 
 | 516 |     return ExprError(); | 
 | 517 |   } | 
 | 518 |  | 
 | 519 |   QualType AtomTy = pointerType->getPointeeType(); | 
 | 520 |   if (!AtomTy->isAtomicType()) { | 
 | 521 |     Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic) | 
 | 522 |       << Ptr->getType() << Ptr->getSourceRange(); | 
 | 523 |     return ExprError(); | 
 | 524 |   } | 
 | 525 |   QualType ValType = AtomTy->getAs<AtomicType>()->getValueType(); | 
 | 526 |  | 
 | 527 |   if ((Op == AtomicExpr::Add || Op == AtomicExpr::Sub) && | 
 | 528 |       !ValType->isIntegerType() && !ValType->isPointerType()) { | 
 | 529 |     Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr) | 
 | 530 |       << Ptr->getType() << Ptr->getSourceRange(); | 
 | 531 |     return ExprError(); | 
 | 532 |   } | 
 | 533 |  | 
 | 534 |   if (!ValType->isIntegerType() && | 
 | 535 |       (Op == AtomicExpr::And || Op == AtomicExpr::Or || Op == AtomicExpr::Xor)){ | 
 | 536 |     Diag(DRE->getLocStart(), diag::err_atomic_op_logical_needs_atomic_int) | 
 | 537 |       << Ptr->getType() << Ptr->getSourceRange(); | 
 | 538 |     return ExprError(); | 
 | 539 |   } | 
 | 540 |  | 
 | 541 |   switch (ValType.getObjCLifetime()) { | 
 | 542 |   case Qualifiers::OCL_None: | 
 | 543 |   case Qualifiers::OCL_ExplicitNone: | 
 | 544 |     // okay | 
 | 545 |     break; | 
 | 546 |  | 
 | 547 |   case Qualifiers::OCL_Weak: | 
 | 548 |   case Qualifiers::OCL_Strong: | 
 | 549 |   case Qualifiers::OCL_Autoreleasing: | 
 | 550 |     Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership) | 
 | 551 |       << ValType << Ptr->getSourceRange(); | 
 | 552 |     return ExprError(); | 
 | 553 |   } | 
 | 554 |  | 
 | 555 |   QualType ResultType = ValType; | 
 | 556 |   if (Op == AtomicExpr::Store) | 
 | 557 |     ResultType = Context.VoidTy; | 
 | 558 |   else if (Op == AtomicExpr::CmpXchgWeak || Op == AtomicExpr::CmpXchgStrong) | 
 | 559 |     ResultType = Context.BoolTy; | 
 | 560 |  | 
 | 561 |   // The first argument --- the pointer --- has a fixed type; we | 
 | 562 |   // deduce the types of the rest of the arguments accordingly.  Walk | 
 | 563 |   // the remaining arguments, converting them to the deduced value type. | 
 | 564 |   for (unsigned i = 1; i != NumVals+NumOrders+1; ++i) { | 
 | 565 |     ExprResult Arg = TheCall->getArg(i); | 
 | 566 |     QualType Ty; | 
 | 567 |     if (i < NumVals+1) { | 
 | 568 |       // The second argument to a cmpxchg is a pointer to the data which will | 
 | 569 |       // be exchanged. The second argument to a pointer add/subtract is the | 
 | 570 |       // amount to add/subtract, which must be a ptrdiff_t.  The third | 
 | 571 |       // argument to a cmpxchg and the second argument in all other cases | 
 | 572 |       // is the type of the value. | 
 | 573 |       if (i == 1 && (Op == AtomicExpr::CmpXchgWeak || | 
 | 574 |                      Op == AtomicExpr::CmpXchgStrong)) | 
 | 575 |          Ty = Context.getPointerType(ValType.getUnqualifiedType()); | 
 | 576 |       else if (!ValType->isIntegerType() && | 
 | 577 |                (Op == AtomicExpr::Add || Op == AtomicExpr::Sub)) | 
 | 578 |         Ty = Context.getPointerDiffType(); | 
 | 579 |       else | 
 | 580 |         Ty = ValType; | 
 | 581 |     } else { | 
 | 582 |       // The order(s) are always converted to int. | 
 | 583 |       Ty = Context.IntTy; | 
 | 584 |     } | 
 | 585 |     InitializedEntity Entity = | 
 | 586 |         InitializedEntity::InitializeParameter(Context, Ty, false); | 
 | 587 |     Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg); | 
 | 588 |     if (Arg.isInvalid()) | 
 | 589 |       return true; | 
 | 590 |     TheCall->setArg(i, Arg.get()); | 
 | 591 |   } | 
 | 592 |  | 
| Eli Friedman | dfa64ba | 2011-10-14 22:48:56 +0000 | [diff] [blame] | 593 |   SmallVector<Expr*, 5> SubExprs; | 
 | 594 |   SubExprs.push_back(Ptr); | 
| Eli Friedman | 276b061 | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 595 |   if (Op == AtomicExpr::Load) { | 
| Eli Friedman | dfa64ba | 2011-10-14 22:48:56 +0000 | [diff] [blame] | 596 |     SubExprs.push_back(TheCall->getArg(1)); // Order | 
| Eli Friedman | 276b061 | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 597 |   } else if (Op != AtomicExpr::CmpXchgWeak && Op != AtomicExpr::CmpXchgStrong) { | 
| Eli Friedman | dfa64ba | 2011-10-14 22:48:56 +0000 | [diff] [blame] | 598 |     SubExprs.push_back(TheCall->getArg(2)); // Order | 
 | 599 |     SubExprs.push_back(TheCall->getArg(1)); // Val1 | 
| Eli Friedman | 276b061 | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 600 |   } else { | 
| Eli Friedman | dfa64ba | 2011-10-14 22:48:56 +0000 | [diff] [blame] | 601 |     SubExprs.push_back(TheCall->getArg(3)); // Order | 
 | 602 |     SubExprs.push_back(TheCall->getArg(1)); // Val1 | 
 | 603 |     SubExprs.push_back(TheCall->getArg(2)); // Val2 | 
 | 604 |     SubExprs.push_back(TheCall->getArg(4)); // OrderFail | 
| Eli Friedman | 276b061 | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 605 |   } | 
| Eli Friedman | dfa64ba | 2011-10-14 22:48:56 +0000 | [diff] [blame] | 606 |  | 
 | 607 |   return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), | 
 | 608 |                                         SubExprs.data(), SubExprs.size(), | 
 | 609 |                                         ResultType, Op, | 
 | 610 |                                         TheCall->getRParenLoc())); | 
| Eli Friedman | 276b061 | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 611 | } | 
 | 612 |  | 
 | 613 |  | 
| John McCall | 5f8d604 | 2011-08-27 01:09:30 +0000 | [diff] [blame] | 614 | /// checkBuiltinArgument - Given a call to a builtin function, perform | 
 | 615 | /// normal type-checking on the given argument, updating the call in | 
 | 616 | /// place.  This is useful when a builtin function requires custom | 
 | 617 | /// type-checking for some of its arguments but not necessarily all of | 
 | 618 | /// them. | 
 | 619 | /// | 
 | 620 | /// Returns true on error. | 
 | 621 | static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) { | 
 | 622 |   FunctionDecl *Fn = E->getDirectCallee(); | 
 | 623 |   assert(Fn && "builtin call without direct callee!"); | 
 | 624 |  | 
 | 625 |   ParmVarDecl *Param = Fn->getParamDecl(ArgIndex); | 
 | 626 |   InitializedEntity Entity = | 
 | 627 |     InitializedEntity::InitializeParameter(S.Context, Param); | 
 | 628 |  | 
 | 629 |   ExprResult Arg = E->getArg(0); | 
 | 630 |   Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg); | 
 | 631 |   if (Arg.isInvalid()) | 
 | 632 |     return true; | 
 | 633 |  | 
 | 634 |   E->setArg(ArgIndex, Arg.take()); | 
 | 635 |   return false; | 
 | 636 | } | 
 | 637 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 638 | /// SemaBuiltinAtomicOverloaded - We have a call to a function like | 
 | 639 | /// __sync_fetch_and_add, which is an overloaded function based on the pointer | 
 | 640 | /// type of its first argument.  The main ActOnCallExpr routines have already | 
 | 641 | /// promoted the types of arguments because all of these calls are prototyped as | 
 | 642 | /// void(...). | 
 | 643 | /// | 
 | 644 | /// This function goes through and does final semantic checking for these | 
 | 645 | /// builtins, | 
| John McCall | 60d7b3a | 2010-08-24 06:29:42 +0000 | [diff] [blame] | 646 | ExprResult | 
 | 647 | Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 648 |   CallExpr *TheCall = (CallExpr *)TheCallResult.get(); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 649 |   DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); | 
 | 650 |   FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl()); | 
 | 651 |  | 
 | 652 |   // Ensure that we have at least one argument to do type inference from. | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 653 |   if (TheCall->getNumArgs() < 1) { | 
 | 654 |     Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) | 
 | 655 |       << 0 << 1 << TheCall->getNumArgs() | 
 | 656 |       << TheCall->getCallee()->getSourceRange(); | 
 | 657 |     return ExprError(); | 
 | 658 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 659 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 660 |   // Inspect the first argument of the atomic builtin.  This should always be | 
 | 661 |   // a pointer type, whose element is an integral scalar or pointer type. | 
 | 662 |   // Because it is a pointer type, we don't have to worry about any implicit | 
 | 663 |   // casts here. | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 664 |   // FIXME: We don't allow floating point scalars as input. | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 665 |   Expr *FirstArg = TheCall->getArg(0); | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 666 |   const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>(); | 
 | 667 |   if (!pointerType) { | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 668 |     Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) | 
 | 669 |       << FirstArg->getType() << FirstArg->getSourceRange(); | 
 | 670 |     return ExprError(); | 
 | 671 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 672 |  | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 673 |   QualType ValType = pointerType->getPointeeType(); | 
| Chris Lattner | dd5fa7a | 2010-09-17 21:12:38 +0000 | [diff] [blame] | 674 |   if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 675 |       !ValType->isBlockPointerType()) { | 
 | 676 |     Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intptr) | 
 | 677 |       << FirstArg->getType() << FirstArg->getSourceRange(); | 
 | 678 |     return ExprError(); | 
 | 679 |   } | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 680 |  | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 681 |   switch (ValType.getObjCLifetime()) { | 
 | 682 |   case Qualifiers::OCL_None: | 
 | 683 |   case Qualifiers::OCL_ExplicitNone: | 
 | 684 |     // okay | 
 | 685 |     break; | 
 | 686 |  | 
 | 687 |   case Qualifiers::OCL_Weak: | 
 | 688 |   case Qualifiers::OCL_Strong: | 
 | 689 |   case Qualifiers::OCL_Autoreleasing: | 
| Argyrios Kyrtzidis | b8b0313 | 2011-06-24 00:08:59 +0000 | [diff] [blame] | 690 |     Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership) | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 691 |       << ValType << FirstArg->getSourceRange(); | 
 | 692 |     return ExprError(); | 
 | 693 |   } | 
 | 694 |  | 
| John McCall | b45ae25 | 2011-10-05 07:41:44 +0000 | [diff] [blame] | 695 |   // Strip any qualifiers off ValType. | 
 | 696 |   ValType = ValType.getUnqualifiedType(); | 
 | 697 |  | 
| Chandler Carruth | 8d13d22 | 2010-07-18 20:54:12 +0000 | [diff] [blame] | 698 |   // The majority of builtins return a value, but a few have special return | 
 | 699 |   // types, so allow them to override appropriately below. | 
 | 700 |   QualType ResultType = ValType; | 
 | 701 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 702 |   // We need to figure out which concrete builtin this maps onto.  For example, | 
 | 703 |   // __sync_fetch_and_add with a 2 byte object turns into | 
 | 704 |   // __sync_fetch_and_add_2. | 
 | 705 | #define BUILTIN_ROW(x) \ | 
 | 706 |   { Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \ | 
 | 707 |     Builtin::BI##x##_8, Builtin::BI##x##_16 } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 708 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 709 |   static const unsigned BuiltinIndices[][5] = { | 
 | 710 |     BUILTIN_ROW(__sync_fetch_and_add), | 
 | 711 |     BUILTIN_ROW(__sync_fetch_and_sub), | 
 | 712 |     BUILTIN_ROW(__sync_fetch_and_or), | 
 | 713 |     BUILTIN_ROW(__sync_fetch_and_and), | 
 | 714 |     BUILTIN_ROW(__sync_fetch_and_xor), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 715 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 716 |     BUILTIN_ROW(__sync_add_and_fetch), | 
 | 717 |     BUILTIN_ROW(__sync_sub_and_fetch), | 
 | 718 |     BUILTIN_ROW(__sync_and_and_fetch), | 
 | 719 |     BUILTIN_ROW(__sync_or_and_fetch), | 
 | 720 |     BUILTIN_ROW(__sync_xor_and_fetch), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 721 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 722 |     BUILTIN_ROW(__sync_val_compare_and_swap), | 
 | 723 |     BUILTIN_ROW(__sync_bool_compare_and_swap), | 
 | 724 |     BUILTIN_ROW(__sync_lock_test_and_set), | 
| Chris Lattner | 23aa9c8 | 2011-04-09 03:57:26 +0000 | [diff] [blame] | 725 |     BUILTIN_ROW(__sync_lock_release), | 
 | 726 |     BUILTIN_ROW(__sync_swap) | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 727 |   }; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 728 | #undef BUILTIN_ROW | 
 | 729 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 730 |   // Determine the index of the size. | 
 | 731 |   unsigned SizeIndex; | 
| Ken Dyck | 199c3d6 | 2010-01-11 17:06:35 +0000 | [diff] [blame] | 732 |   switch (Context.getTypeSizeInChars(ValType).getQuantity()) { | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 733 |   case 1: SizeIndex = 0; break; | 
 | 734 |   case 2: SizeIndex = 1; break; | 
 | 735 |   case 4: SizeIndex = 2; break; | 
 | 736 |   case 8: SizeIndex = 3; break; | 
 | 737 |   case 16: SizeIndex = 4; break; | 
 | 738 |   default: | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 739 |     Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size) | 
 | 740 |       << FirstArg->getType() << FirstArg->getSourceRange(); | 
 | 741 |     return ExprError(); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 742 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 743 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 744 |   // Each of these builtins has one pointer argument, followed by some number of | 
 | 745 |   // values (0, 1 or 2) followed by a potentially empty varags list of stuff | 
 | 746 |   // that we ignore.  Find out which row of BuiltinIndices to read from as well | 
 | 747 |   // as the number of fixed args. | 
| Douglas Gregor | 7814e6d | 2009-09-12 00:22:50 +0000 | [diff] [blame] | 748 |   unsigned BuiltinID = FDecl->getBuiltinID(); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 749 |   unsigned BuiltinIndex, NumFixed = 1; | 
 | 750 |   switch (BuiltinID) { | 
| David Blaikie | b219cfc | 2011-09-23 05:06:16 +0000 | [diff] [blame] | 751 |   default: llvm_unreachable("Unknown overloaded atomic builtin!"); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 752 |   case Builtin::BI__sync_fetch_and_add: BuiltinIndex = 0; break; | 
 | 753 |   case Builtin::BI__sync_fetch_and_sub: BuiltinIndex = 1; break; | 
 | 754 |   case Builtin::BI__sync_fetch_and_or:  BuiltinIndex = 2; break; | 
 | 755 |   case Builtin::BI__sync_fetch_and_and: BuiltinIndex = 3; break; | 
 | 756 |   case Builtin::BI__sync_fetch_and_xor: BuiltinIndex = 4; break; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 757 |  | 
| Daniel Dunbar | 7eff7c4 | 2010-03-25 17:13:09 +0000 | [diff] [blame] | 758 |   case Builtin::BI__sync_add_and_fetch: BuiltinIndex = 5; break; | 
 | 759 |   case Builtin::BI__sync_sub_and_fetch: BuiltinIndex = 6; break; | 
 | 760 |   case Builtin::BI__sync_and_and_fetch: BuiltinIndex = 7; break; | 
 | 761 |   case Builtin::BI__sync_or_and_fetch:  BuiltinIndex = 8; break; | 
 | 762 |   case Builtin::BI__sync_xor_and_fetch: BuiltinIndex = 9; break; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 763 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 764 |   case Builtin::BI__sync_val_compare_and_swap: | 
| Daniel Dunbar | 7eff7c4 | 2010-03-25 17:13:09 +0000 | [diff] [blame] | 765 |     BuiltinIndex = 10; | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 766 |     NumFixed = 2; | 
 | 767 |     break; | 
 | 768 |   case Builtin::BI__sync_bool_compare_and_swap: | 
| Daniel Dunbar | 7eff7c4 | 2010-03-25 17:13:09 +0000 | [diff] [blame] | 769 |     BuiltinIndex = 11; | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 770 |     NumFixed = 2; | 
| Chandler Carruth | 8d13d22 | 2010-07-18 20:54:12 +0000 | [diff] [blame] | 771 |     ResultType = Context.BoolTy; | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 772 |     break; | 
| Daniel Dunbar | 7eff7c4 | 2010-03-25 17:13:09 +0000 | [diff] [blame] | 773 |   case Builtin::BI__sync_lock_test_and_set: BuiltinIndex = 12; break; | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 774 |   case Builtin::BI__sync_lock_release: | 
| Daniel Dunbar | 7eff7c4 | 2010-03-25 17:13:09 +0000 | [diff] [blame] | 775 |     BuiltinIndex = 13; | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 776 |     NumFixed = 0; | 
| Chandler Carruth | 8d13d22 | 2010-07-18 20:54:12 +0000 | [diff] [blame] | 777 |     ResultType = Context.VoidTy; | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 778 |     break; | 
| Chris Lattner | 23aa9c8 | 2011-04-09 03:57:26 +0000 | [diff] [blame] | 779 |   case Builtin::BI__sync_swap: BuiltinIndex = 14; break; | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 780 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 781 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 782 |   // Now that we know how many fixed arguments we expect, first check that we | 
 | 783 |   // have at least that many. | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 784 |   if (TheCall->getNumArgs() < 1+NumFixed) { | 
 | 785 |     Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) | 
 | 786 |       << 0 << 1+NumFixed << TheCall->getNumArgs() | 
 | 787 |       << TheCall->getCallee()->getSourceRange(); | 
 | 788 |     return ExprError(); | 
 | 789 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 790 |  | 
| Chris Lattner | e7ac0a9 | 2009-05-08 15:36:58 +0000 | [diff] [blame] | 791 |   // Get the decl for the concrete builtin from this, we can tell what the | 
 | 792 |   // concrete integer type we should convert to is. | 
 | 793 |   unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex]; | 
 | 794 |   const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID); | 
 | 795 |   IdentifierInfo *NewBuiltinII = PP.getIdentifierInfo(NewBuiltinName); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 796 |   FunctionDecl *NewBuiltinDecl = | 
| Chris Lattner | e7ac0a9 | 2009-05-08 15:36:58 +0000 | [diff] [blame] | 797 |     cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID, | 
 | 798 |                                            TUScope, false, DRE->getLocStart())); | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 799 |  | 
| John McCall | f871d0c | 2010-08-07 06:22:56 +0000 | [diff] [blame] | 800 |   // The first argument --- the pointer --- has a fixed type; we | 
 | 801 |   // deduce the types of the rest of the arguments accordingly.  Walk | 
 | 802 |   // the remaining arguments, converting them to the deduced value type. | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 803 |   for (unsigned i = 0; i != NumFixed; ++i) { | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 804 |     ExprResult Arg = TheCall->getArg(i+1); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 805 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 806 |     // If the argument is an implicit cast, then there was a promotion due to | 
 | 807 |     // "...", just remove it now. | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 808 |     if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg.get())) { | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 809 |       Arg = ICE->getSubExpr(); | 
 | 810 |       ICE->setSubExpr(0); | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 811 |       TheCall->setArg(i+1, Arg.get()); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 812 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 813 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 814 |     // GCC does an implicit conversion to the pointer or integer ValType.  This | 
 | 815 |     // can fail in some cases (1i -> int**), check for this error case now. | 
| John McCall | b45ae25 | 2011-10-05 07:41:44 +0000 | [diff] [blame] | 816 |     // Initialize the argument. | 
 | 817 |     InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, | 
 | 818 |                                                    ValType, /*consume*/ false); | 
 | 819 |     Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg); | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 820 |     if (Arg.isInvalid()) | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 821 |       return ExprError(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 822 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 823 |     // Okay, we have something that *can* be converted to the right type.  Check | 
 | 824 |     // to see if there is a potentially weird extension going on here.  This can | 
 | 825 |     // happen when you do an atomic operation on something like an char* and | 
 | 826 |     // pass in 42.  The 42 gets converted to char.  This is even more strange | 
 | 827 |     // for things like 45.123 -> char, etc. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 828 |     // FIXME: Do this check. | 
| John McCall | b45ae25 | 2011-10-05 07:41:44 +0000 | [diff] [blame] | 829 |     TheCall->setArg(i+1, Arg.take()); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 830 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 831 |  | 
| Douglas Gregor | bbcb7ea | 2011-09-09 16:51:10 +0000 | [diff] [blame] | 832 |   ASTContext& Context = this->getASTContext(); | 
 | 833 |  | 
 | 834 |   // Create a new DeclRefExpr to refer to the new decl. | 
 | 835 |   DeclRefExpr* NewDRE = DeclRefExpr::Create( | 
 | 836 |       Context, | 
 | 837 |       DRE->getQualifierLoc(), | 
 | 838 |       NewBuiltinDecl, | 
 | 839 |       DRE->getLocation(), | 
 | 840 |       NewBuiltinDecl->getType(), | 
 | 841 |       DRE->getValueKind()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 842 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 843 |   // Set the callee in the CallExpr. | 
 | 844 |   // FIXME: This leaks the original parens and implicit casts. | 
| Douglas Gregor | bbcb7ea | 2011-09-09 16:51:10 +0000 | [diff] [blame] | 845 |   ExprResult PromotedCall = UsualUnaryConversions(NewDRE); | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 846 |   if (PromotedCall.isInvalid()) | 
 | 847 |     return ExprError(); | 
 | 848 |   TheCall->setCallee(PromotedCall.take()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 849 |  | 
| Chandler Carruth | db4325b | 2010-07-18 07:23:17 +0000 | [diff] [blame] | 850 |   // Change the result type of the call to match the original value type. This | 
 | 851 |   // is arbitrary, but the codegen for these builtins ins design to handle it | 
 | 852 |   // gracefully. | 
| Chandler Carruth | 8d13d22 | 2010-07-18 20:54:12 +0000 | [diff] [blame] | 853 |   TheCall->setType(ResultType); | 
| Chandler Carruth | d201457 | 2010-07-09 18:59:35 +0000 | [diff] [blame] | 854 |  | 
 | 855 |   return move(TheCallResult); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 856 | } | 
 | 857 |  | 
| Chris Lattner | 6903981 | 2009-02-18 06:01:06 +0000 | [diff] [blame] | 858 | /// CheckObjCString - Checks that the argument to the builtin | 
| Anders Carlsson | 71993dd | 2007-08-17 05:31:46 +0000 | [diff] [blame] | 859 | /// CFString constructor is correct | 
| Steve Naroff | fd94262 | 2009-04-13 20:26:29 +0000 | [diff] [blame] | 860 | /// Note: It might also make sense to do the UTF-16 conversion here (would | 
 | 861 | /// simplify the backend). | 
| Chris Lattner | 6903981 | 2009-02-18 06:01:06 +0000 | [diff] [blame] | 862 | bool Sema::CheckObjCString(Expr *Arg) { | 
| Chris Lattner | 56f3494 | 2008-02-13 01:02:39 +0000 | [diff] [blame] | 863 |   Arg = Arg->IgnoreParenCasts(); | 
| Anders Carlsson | 71993dd | 2007-08-17 05:31:46 +0000 | [diff] [blame] | 864 |   StringLiteral *Literal = dyn_cast<StringLiteral>(Arg); | 
 | 865 |  | 
| Douglas Gregor | 5cee119 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 866 |   if (!Literal || !Literal->isAscii()) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 867 |     Diag(Arg->getLocStart(), diag::err_cfstring_literal_not_string_constant) | 
 | 868 |       << Arg->getSourceRange(); | 
| Anders Carlsson | 9cdc4d3 | 2007-08-17 15:44:17 +0000 | [diff] [blame] | 869 |     return true; | 
| Anders Carlsson | 71993dd | 2007-08-17 05:31:46 +0000 | [diff] [blame] | 870 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 871 |  | 
| Fariborz Jahanian | 7da7102 | 2010-09-07 19:38:13 +0000 | [diff] [blame] | 872 |   if (Literal->containsNonAsciiOrNull()) { | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 873 |     StringRef String = Literal->getString(); | 
| Fariborz Jahanian | 7da7102 | 2010-09-07 19:38:13 +0000 | [diff] [blame] | 874 |     unsigned NumBytes = String.size(); | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 875 |     SmallVector<UTF16, 128> ToBuf(NumBytes); | 
| Fariborz Jahanian | 7da7102 | 2010-09-07 19:38:13 +0000 | [diff] [blame] | 876 |     const UTF8 *FromPtr = (UTF8 *)String.data(); | 
 | 877 |     UTF16 *ToPtr = &ToBuf[0]; | 
 | 878 |      | 
 | 879 |     ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, | 
 | 880 |                                                  &ToPtr, ToPtr + NumBytes, | 
 | 881 |                                                  strictConversion); | 
 | 882 |     // Check for conversion failure. | 
 | 883 |     if (Result != conversionOK) | 
 | 884 |       Diag(Arg->getLocStart(), | 
 | 885 |            diag::warn_cfstring_truncated) << Arg->getSourceRange(); | 
 | 886 |   } | 
| Anders Carlsson | 9cdc4d3 | 2007-08-17 15:44:17 +0000 | [diff] [blame] | 887 |   return false; | 
| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 888 | } | 
 | 889 |  | 
| Chris Lattner | c27c665 | 2007-12-20 00:05:45 +0000 | [diff] [blame] | 890 | /// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity. | 
 | 891 | /// Emit an error and return true on failure, return false on success. | 
| Chris Lattner | 925e60d | 2007-12-28 05:29:59 +0000 | [diff] [blame] | 892 | bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { | 
 | 893 |   Expr *Fn = TheCall->getCallee(); | 
 | 894 |   if (TheCall->getNumArgs() > 2) { | 
| Chris Lattner | 2c21a07 | 2008-11-21 18:44:24 +0000 | [diff] [blame] | 895 |     Diag(TheCall->getArg(2)->getLocStart(), | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 896 |          diag::err_typecheck_call_too_many_args) | 
| Eric Christopher | ccfa963 | 2010-04-16 04:56:46 +0000 | [diff] [blame] | 897 |       << 0 /*function call*/ << 2 << TheCall->getNumArgs() | 
 | 898 |       << Fn->getSourceRange() | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 899 |       << SourceRange(TheCall->getArg(2)->getLocStart(), | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 900 |                      (*(TheCall->arg_end()-1))->getLocEnd()); | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 901 |     return true; | 
 | 902 |   } | 
| Eli Friedman | 56f20ae | 2008-12-15 22:05:35 +0000 | [diff] [blame] | 903 |  | 
 | 904 |   if (TheCall->getNumArgs() < 2) { | 
| Eric Christopher | d77b9a2 | 2010-04-16 04:48:22 +0000 | [diff] [blame] | 905 |     return Diag(TheCall->getLocEnd(), | 
 | 906 |       diag::err_typecheck_call_too_few_args_at_least) | 
 | 907 |       << 0 /*function call*/ << 2 << TheCall->getNumArgs(); | 
| Eli Friedman | 56f20ae | 2008-12-15 22:05:35 +0000 | [diff] [blame] | 908 |   } | 
 | 909 |  | 
| John McCall | 5f8d604 | 2011-08-27 01:09:30 +0000 | [diff] [blame] | 910 |   // Type-check the first argument normally. | 
 | 911 |   if (checkBuiltinArgument(*this, TheCall, 0)) | 
 | 912 |     return true; | 
 | 913 |  | 
| Chris Lattner | c27c665 | 2007-12-20 00:05:45 +0000 | [diff] [blame] | 914 |   // Determine whether the current function is variadic or not. | 
| Douglas Gregor | 9ea9bdb | 2010-03-01 23:15:13 +0000 | [diff] [blame] | 915 |   BlockScopeInfo *CurBlock = getCurBlock(); | 
| Chris Lattner | c27c665 | 2007-12-20 00:05:45 +0000 | [diff] [blame] | 916 |   bool isVariadic; | 
| Steve Naroff | cd9c514 | 2009-04-15 19:33:47 +0000 | [diff] [blame] | 917 |   if (CurBlock) | 
| John McCall | c71a491 | 2010-06-04 19:02:56 +0000 | [diff] [blame] | 918 |     isVariadic = CurBlock->TheDecl->isVariadic(); | 
| Ted Kremenek | 9498d38 | 2010-04-29 16:49:01 +0000 | [diff] [blame] | 919 |   else if (FunctionDecl *FD = getCurFunctionDecl()) | 
 | 920 |     isVariadic = FD->isVariadic(); | 
 | 921 |   else | 
| Argyrios Kyrtzidis | 53d0ea5 | 2008-06-28 06:07:14 +0000 | [diff] [blame] | 922 |     isVariadic = getCurMethodDecl()->isVariadic(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 923 |  | 
| Chris Lattner | c27c665 | 2007-12-20 00:05:45 +0000 | [diff] [blame] | 924 |   if (!isVariadic) { | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 925 |     Diag(Fn->getLocStart(), diag::err_va_start_used_in_non_variadic_function); | 
 | 926 |     return true; | 
 | 927 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 928 |  | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 929 |   // Verify that the second argument to the builtin is the last argument of the | 
 | 930 |   // current function or method. | 
 | 931 |   bool SecondArgIsLastNamedArgument = false; | 
| Anders Carlsson | e2c1410 | 2008-02-13 01:22:59 +0000 | [diff] [blame] | 932 |   const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 933 |  | 
| Anders Carlsson | 88cf226 | 2008-02-11 04:20:54 +0000 | [diff] [blame] | 934 |   if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) { | 
 | 935 |     if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) { | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 936 |       // FIXME: This isn't correct for methods (results in bogus warning). | 
 | 937 |       // Get the last formal in the current function. | 
| Anders Carlsson | 88cf226 | 2008-02-11 04:20:54 +0000 | [diff] [blame] | 938 |       const ParmVarDecl *LastArg; | 
| Steve Naroff | cd9c514 | 2009-04-15 19:33:47 +0000 | [diff] [blame] | 939 |       if (CurBlock) | 
 | 940 |         LastArg = *(CurBlock->TheDecl->param_end()-1); | 
 | 941 |       else if (FunctionDecl *FD = getCurFunctionDecl()) | 
| Chris Lattner | 371f258 | 2008-12-04 23:50:19 +0000 | [diff] [blame] | 942 |         LastArg = *(FD->param_end()-1); | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 943 |       else | 
| Argyrios Kyrtzidis | 53d0ea5 | 2008-06-28 06:07:14 +0000 | [diff] [blame] | 944 |         LastArg = *(getCurMethodDecl()->param_end()-1); | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 945 |       SecondArgIsLastNamedArgument = PV == LastArg; | 
 | 946 |     } | 
 | 947 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 948 |  | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 949 |   if (!SecondArgIsLastNamedArgument) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 950 |     Diag(TheCall->getArg(1)->getLocStart(), | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 951 |          diag::warn_second_parameter_of_va_start_not_last_named_argument); | 
 | 952 |   return false; | 
| Eli Friedman | 6cfda23 | 2008-05-20 08:23:37 +0000 | [diff] [blame] | 953 | } | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 954 |  | 
| Chris Lattner | 1b9a079 | 2007-12-20 00:26:33 +0000 | [diff] [blame] | 955 | /// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and | 
 | 956 | /// friends.  This is declared to take (...), so we have to check everything. | 
| Chris Lattner | 925e60d | 2007-12-28 05:29:59 +0000 | [diff] [blame] | 957 | bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { | 
 | 958 |   if (TheCall->getNumArgs() < 2) | 
| Chris Lattner | 2c21a07 | 2008-11-21 18:44:24 +0000 | [diff] [blame] | 959 |     return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) | 
| Eric Christopher | d77b9a2 | 2010-04-16 04:48:22 +0000 | [diff] [blame] | 960 |       << 0 << 2 << TheCall->getNumArgs()/*function call*/; | 
| Chris Lattner | 925e60d | 2007-12-28 05:29:59 +0000 | [diff] [blame] | 961 |   if (TheCall->getNumArgs() > 2) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 962 |     return Diag(TheCall->getArg(2)->getLocStart(), | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 963 |                 diag::err_typecheck_call_too_many_args) | 
| Eric Christopher | ccfa963 | 2010-04-16 04:56:46 +0000 | [diff] [blame] | 964 |       << 0 /*function call*/ << 2 << TheCall->getNumArgs() | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 965 |       << SourceRange(TheCall->getArg(2)->getLocStart(), | 
 | 966 |                      (*(TheCall->arg_end()-1))->getLocEnd()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 967 |  | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 968 |   ExprResult OrigArg0 = TheCall->getArg(0); | 
 | 969 |   ExprResult OrigArg1 = TheCall->getArg(1); | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 970 |  | 
| Chris Lattner | 1b9a079 | 2007-12-20 00:26:33 +0000 | [diff] [blame] | 971 |   // Do standard promotions between the two arguments, returning their common | 
 | 972 |   // type. | 
| Chris Lattner | 925e60d | 2007-12-28 05:29:59 +0000 | [diff] [blame] | 973 |   QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false); | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 974 |   if (OrigArg0.isInvalid() || OrigArg1.isInvalid()) | 
 | 975 |     return true; | 
| Daniel Dunbar | 403bc2b | 2009-02-19 19:28:43 +0000 | [diff] [blame] | 976 |  | 
 | 977 |   // Make sure any conversions are pushed back into the call; this is | 
 | 978 |   // type safe since unordered compare builtins are declared as "_Bool | 
 | 979 |   // foo(...)". | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 980 |   TheCall->setArg(0, OrigArg0.get()); | 
 | 981 |   TheCall->setArg(1, OrigArg1.get()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 982 |  | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 983 |   if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent()) | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 984 |     return false; | 
 | 985 |  | 
| Chris Lattner | 1b9a079 | 2007-12-20 00:26:33 +0000 | [diff] [blame] | 986 |   // If the common type isn't a real floating type, then the arguments were | 
 | 987 |   // invalid for this operation. | 
 | 988 |   if (!Res->isRealFloatingType()) | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 989 |     return Diag(OrigArg0.get()->getLocStart(), | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 990 |                 diag::err_typecheck_call_invalid_ordered_compare) | 
| John Wiegley | 429bb27 | 2011-04-08 18:41:53 +0000 | [diff] [blame] | 991 |       << OrigArg0.get()->getType() << OrigArg1.get()->getType() | 
 | 992 |       << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 993 |  | 
| Chris Lattner | 1b9a079 | 2007-12-20 00:26:33 +0000 | [diff] [blame] | 994 |   return false; | 
 | 995 | } | 
 | 996 |  | 
| Benjamin Kramer | e771a7a | 2010-02-15 22:42:31 +0000 | [diff] [blame] | 997 | /// SemaBuiltinSemaBuiltinFPClassification - Handle functions like | 
 | 998 | /// __builtin_isnan and friends.  This is declared to take (...), so we have | 
| Benjamin Kramer | 3b1e26b | 2010-02-16 10:07:31 +0000 | [diff] [blame] | 999 | /// to check everything. We expect the last argument to be a floating point | 
 | 1000 | /// value. | 
 | 1001 | bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { | 
 | 1002 |   if (TheCall->getNumArgs() < NumArgs) | 
| Eli Friedman | 9ac6f62 | 2009-08-31 20:06:00 +0000 | [diff] [blame] | 1003 |     return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) | 
| Eric Christopher | d77b9a2 | 2010-04-16 04:48:22 +0000 | [diff] [blame] | 1004 |       << 0 << NumArgs << TheCall->getNumArgs()/*function call*/; | 
| Benjamin Kramer | 3b1e26b | 2010-02-16 10:07:31 +0000 | [diff] [blame] | 1005 |   if (TheCall->getNumArgs() > NumArgs) | 
 | 1006 |     return Diag(TheCall->getArg(NumArgs)->getLocStart(), | 
| Eli Friedman | 9ac6f62 | 2009-08-31 20:06:00 +0000 | [diff] [blame] | 1007 |                 diag::err_typecheck_call_too_many_args) | 
| Eric Christopher | ccfa963 | 2010-04-16 04:56:46 +0000 | [diff] [blame] | 1008 |       << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() | 
| Benjamin Kramer | 3b1e26b | 2010-02-16 10:07:31 +0000 | [diff] [blame] | 1009 |       << SourceRange(TheCall->getArg(NumArgs)->getLocStart(), | 
| Eli Friedman | 9ac6f62 | 2009-08-31 20:06:00 +0000 | [diff] [blame] | 1010 |                      (*(TheCall->arg_end()-1))->getLocEnd()); | 
 | 1011 |  | 
| Benjamin Kramer | 3b1e26b | 2010-02-16 10:07:31 +0000 | [diff] [blame] | 1012 |   Expr *OrigArg = TheCall->getArg(NumArgs-1); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1013 |  | 
| Eli Friedman | 9ac6f62 | 2009-08-31 20:06:00 +0000 | [diff] [blame] | 1014 |   if (OrigArg->isTypeDependent()) | 
 | 1015 |     return false; | 
 | 1016 |  | 
| Chris Lattner | 81368fb | 2010-05-06 05:50:07 +0000 | [diff] [blame] | 1017 |   // This operation requires a non-_Complex floating-point number. | 
| Eli Friedman | 9ac6f62 | 2009-08-31 20:06:00 +0000 | [diff] [blame] | 1018 |   if (!OrigArg->getType()->isRealFloatingType()) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1019 |     return Diag(OrigArg->getLocStart(), | 
| Eli Friedman | 9ac6f62 | 2009-08-31 20:06:00 +0000 | [diff] [blame] | 1020 |                 diag::err_typecheck_call_invalid_unary_fp) | 
 | 1021 |       << OrigArg->getType() << OrigArg->getSourceRange(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1022 |  | 
| Chris Lattner | 81368fb | 2010-05-06 05:50:07 +0000 | [diff] [blame] | 1023 |   // If this is an implicit conversion from float -> double, remove it. | 
 | 1024 |   if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) { | 
 | 1025 |     Expr *CastArg = Cast->getSubExpr(); | 
 | 1026 |     if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { | 
 | 1027 |       assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) && | 
 | 1028 |              "promotion from float to double is the only expected cast here"); | 
 | 1029 |       Cast->setSubExpr(0); | 
| Chris Lattner | 81368fb | 2010-05-06 05:50:07 +0000 | [diff] [blame] | 1030 |       TheCall->setArg(NumArgs-1, CastArg); | 
 | 1031 |       OrigArg = CastArg; | 
 | 1032 |     } | 
 | 1033 |   } | 
 | 1034 |    | 
| Eli Friedman | 9ac6f62 | 2009-08-31 20:06:00 +0000 | [diff] [blame] | 1035 |   return false; | 
 | 1036 | } | 
 | 1037 |  | 
| Eli Friedman | d38617c | 2008-05-14 19:38:39 +0000 | [diff] [blame] | 1038 | /// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. | 
 | 1039 | // This is declared to take (...), so we have to check everything. | 
| John McCall | 60d7b3a | 2010-08-24 06:29:42 +0000 | [diff] [blame] | 1040 | ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { | 
| Nate Begeman | 37b6a57 | 2010-06-08 00:16:34 +0000 | [diff] [blame] | 1041 |   if (TheCall->getNumArgs() < 2) | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 1042 |     return ExprError(Diag(TheCall->getLocEnd(), | 
| Eric Christopher | d77b9a2 | 2010-04-16 04:48:22 +0000 | [diff] [blame] | 1043 |                           diag::err_typecheck_call_too_few_args_at_least) | 
| Nate Begeman | 37b6a57 | 2010-06-08 00:16:34 +0000 | [diff] [blame] | 1044 |       << 0 /*function call*/ << 2 << TheCall->getNumArgs() | 
| Eric Christopher | d77b9a2 | 2010-04-16 04:48:22 +0000 | [diff] [blame] | 1045 |       << TheCall->getSourceRange()); | 
| Eli Friedman | d38617c | 2008-05-14 19:38:39 +0000 | [diff] [blame] | 1046 |  | 
| Nate Begeman | 37b6a57 | 2010-06-08 00:16:34 +0000 | [diff] [blame] | 1047 |   // Determine which of the following types of shufflevector we're checking: | 
 | 1048 |   // 1) unary, vector mask: (lhs, mask) | 
 | 1049 |   // 2) binary, vector mask: (lhs, rhs, mask) | 
 | 1050 |   // 3) binary, scalar mask: (lhs, rhs, index, ..., index) | 
 | 1051 |   QualType resType = TheCall->getArg(0)->getType(); | 
 | 1052 |   unsigned numElements = 0; | 
 | 1053 |    | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 1054 |   if (!TheCall->getArg(0)->isTypeDependent() && | 
 | 1055 |       !TheCall->getArg(1)->isTypeDependent()) { | 
| Nate Begeman | 37b6a57 | 2010-06-08 00:16:34 +0000 | [diff] [blame] | 1056 |     QualType LHSType = TheCall->getArg(0)->getType(); | 
 | 1057 |     QualType RHSType = TheCall->getArg(1)->getType(); | 
 | 1058 |      | 
 | 1059 |     if (!LHSType->isVectorType() || !RHSType->isVectorType()) { | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 1060 |       Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1061 |         << SourceRange(TheCall->getArg(0)->getLocStart(), | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 1062 |                        TheCall->getArg(1)->getLocEnd()); | 
 | 1063 |       return ExprError(); | 
 | 1064 |     } | 
| Nate Begeman | 37b6a57 | 2010-06-08 00:16:34 +0000 | [diff] [blame] | 1065 |      | 
 | 1066 |     numElements = LHSType->getAs<VectorType>()->getNumElements(); | 
 | 1067 |     unsigned numResElements = TheCall->getNumArgs() - 2; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1068 |  | 
| Nate Begeman | 37b6a57 | 2010-06-08 00:16:34 +0000 | [diff] [blame] | 1069 |     // Check to see if we have a call with 2 vector arguments, the unary shuffle | 
 | 1070 |     // with mask.  If so, verify that RHS is an integer vector type with the | 
 | 1071 |     // same number of elts as lhs. | 
 | 1072 |     if (TheCall->getNumArgs() == 2) { | 
| Douglas Gregor | f609462 | 2010-07-23 15:58:24 +0000 | [diff] [blame] | 1073 |       if (!RHSType->hasIntegerRepresentation() ||  | 
| Nate Begeman | 37b6a57 | 2010-06-08 00:16:34 +0000 | [diff] [blame] | 1074 |           RHSType->getAs<VectorType>()->getNumElements() != numElements) | 
 | 1075 |         Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) | 
 | 1076 |           << SourceRange(TheCall->getArg(1)->getLocStart(), | 
 | 1077 |                          TheCall->getArg(1)->getLocEnd()); | 
 | 1078 |       numResElements = numElements; | 
 | 1079 |     } | 
 | 1080 |     else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 1081 |       Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1082 |         << SourceRange(TheCall->getArg(0)->getLocStart(), | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 1083 |                        TheCall->getArg(1)->getLocEnd()); | 
 | 1084 |       return ExprError(); | 
| Nate Begeman | 37b6a57 | 2010-06-08 00:16:34 +0000 | [diff] [blame] | 1085 |     } else if (numElements != numResElements) { | 
 | 1086 |       QualType eltType = LHSType->getAs<VectorType>()->getElementType(); | 
| Chris Lattner | 788b0fd | 2010-06-23 06:00:24 +0000 | [diff] [blame] | 1087 |       resType = Context.getVectorType(eltType, numResElements, | 
| Bob Wilson | e86d78c | 2010-11-10 21:56:12 +0000 | [diff] [blame] | 1088 |                                       VectorType::GenericVector); | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 1089 |     } | 
| Eli Friedman | d38617c | 2008-05-14 19:38:39 +0000 | [diff] [blame] | 1090 |   } | 
 | 1091 |  | 
 | 1092 |   for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 1093 |     if (TheCall->getArg(i)->isTypeDependent() || | 
 | 1094 |         TheCall->getArg(i)->isValueDependent()) | 
 | 1095 |       continue; | 
 | 1096 |  | 
| Nate Begeman | 37b6a57 | 2010-06-08 00:16:34 +0000 | [diff] [blame] | 1097 |     llvm::APSInt Result(32); | 
 | 1098 |     if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) | 
 | 1099 |       return ExprError(Diag(TheCall->getLocStart(), | 
 | 1100 |                   diag::err_shufflevector_nonconstant_argument) | 
 | 1101 |                 << TheCall->getArg(i)->getSourceRange()); | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 1102 |  | 
| Chris Lattner | d1a0b6d | 2008-08-10 02:05:13 +0000 | [diff] [blame] | 1103 |     if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 1104 |       return ExprError(Diag(TheCall->getLocStart(), | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1105 |                   diag::err_shufflevector_argument_too_large) | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 1106 |                << TheCall->getArg(i)->getSourceRange()); | 
| Eli Friedman | d38617c | 2008-05-14 19:38:39 +0000 | [diff] [blame] | 1107 |   } | 
 | 1108 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 1109 |   SmallVector<Expr*, 32> exprs; | 
| Eli Friedman | d38617c | 2008-05-14 19:38:39 +0000 | [diff] [blame] | 1110 |  | 
| Chris Lattner | d1a0b6d | 2008-08-10 02:05:13 +0000 | [diff] [blame] | 1111 |   for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) { | 
| Eli Friedman | d38617c | 2008-05-14 19:38:39 +0000 | [diff] [blame] | 1112 |     exprs.push_back(TheCall->getArg(i)); | 
 | 1113 |     TheCall->setArg(i, 0); | 
 | 1114 |   } | 
 | 1115 |  | 
| Nate Begeman | a88dc30 | 2009-08-12 02:10:25 +0000 | [diff] [blame] | 1116 |   return Owned(new (Context) ShuffleVectorExpr(Context, exprs.begin(), | 
| Nate Begeman | 37b6a57 | 2010-06-08 00:16:34 +0000 | [diff] [blame] | 1117 |                                             exprs.size(), resType, | 
| Ted Kremenek | 8189cde | 2009-02-07 01:47:29 +0000 | [diff] [blame] | 1118 |                                             TheCall->getCallee()->getLocStart(), | 
 | 1119 |                                             TheCall->getRParenLoc())); | 
| Eli Friedman | d38617c | 2008-05-14 19:38:39 +0000 | [diff] [blame] | 1120 | } | 
| Chris Lattner | 30ce344 | 2007-12-19 23:59:04 +0000 | [diff] [blame] | 1121 |  | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 1122 | /// SemaBuiltinPrefetch - Handle __builtin_prefetch. | 
 | 1123 | // This is declared to take (const void*, ...) and can take two | 
 | 1124 | // optional constant int args. | 
 | 1125 | bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1126 |   unsigned NumArgs = TheCall->getNumArgs(); | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 1127 |  | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1128 |   if (NumArgs > 3) | 
| Eric Christopher | ccfa963 | 2010-04-16 04:56:46 +0000 | [diff] [blame] | 1129 |     return Diag(TheCall->getLocEnd(), | 
 | 1130 |              diag::err_typecheck_call_too_many_args_at_most) | 
 | 1131 |              << 0 /*function call*/ << 3 << NumArgs | 
 | 1132 |              << TheCall->getSourceRange(); | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 1133 |  | 
 | 1134 |   // Argument 0 is checked for us and the remaining arguments must be | 
 | 1135 |   // constant integers. | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1136 |   for (unsigned i = 1; i != NumArgs; ++i) { | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 1137 |     Expr *Arg = TheCall->getArg(i); | 
| Eric Christopher | 691ebc3 | 2010-04-17 02:26:23 +0000 | [diff] [blame] | 1138 |      | 
| Eli Friedman | 9aef726 | 2009-12-04 00:30:06 +0000 | [diff] [blame] | 1139 |     llvm::APSInt Result; | 
| Eric Christopher | 691ebc3 | 2010-04-17 02:26:23 +0000 | [diff] [blame] | 1140 |     if (SemaBuiltinConstantArg(TheCall, i, Result)) | 
 | 1141 |       return true; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1142 |  | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 1143 |     // FIXME: gcc issues a warning and rewrites these to 0. These | 
 | 1144 |     // seems especially odd for the third argument since the default | 
 | 1145 |     // is 3. | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1146 |     if (i == 1) { | 
| Eli Friedman | 9aef726 | 2009-12-04 00:30:06 +0000 | [diff] [blame] | 1147 |       if (Result.getLimitedValue() > 1) | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1148 |         return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) | 
| Chris Lattner | 21fb98e | 2009-09-23 06:06:36 +0000 | [diff] [blame] | 1149 |              << "0" << "1" << Arg->getSourceRange(); | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 1150 |     } else { | 
| Eli Friedman | 9aef726 | 2009-12-04 00:30:06 +0000 | [diff] [blame] | 1151 |       if (Result.getLimitedValue() > 3) | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1152 |         return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) | 
| Chris Lattner | 21fb98e | 2009-09-23 06:06:36 +0000 | [diff] [blame] | 1153 |             << "0" << "3" << Arg->getSourceRange(); | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 1154 |     } | 
 | 1155 |   } | 
 | 1156 |  | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1157 |   return false; | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 1158 | } | 
 | 1159 |  | 
| Eric Christopher | 691ebc3 | 2010-04-17 02:26:23 +0000 | [diff] [blame] | 1160 | /// SemaBuiltinConstantArg - Handle a check if argument ArgNum of CallExpr | 
 | 1161 | /// TheCall is a constant expression. | 
 | 1162 | bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, | 
 | 1163 |                                   llvm::APSInt &Result) { | 
 | 1164 |   Expr *Arg = TheCall->getArg(ArgNum); | 
 | 1165 |   DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); | 
 | 1166 |   FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl()); | 
 | 1167 |    | 
 | 1168 |   if (Arg->isTypeDependent() || Arg->isValueDependent()) return false; | 
 | 1169 |    | 
 | 1170 |   if (!Arg->isIntegerConstantExpr(Result, Context)) | 
 | 1171 |     return Diag(TheCall->getLocStart(), diag::err_constant_integer_arg_type) | 
| Eric Christopher | 5e89655 | 2010-04-19 18:23:02 +0000 | [diff] [blame] | 1172 |                 << FDecl->getDeclName() <<  Arg->getSourceRange(); | 
| Eric Christopher | 691ebc3 | 2010-04-17 02:26:23 +0000 | [diff] [blame] | 1173 |    | 
| Chris Lattner | 21fb98e | 2009-09-23 06:06:36 +0000 | [diff] [blame] | 1174 |   return false; | 
 | 1175 | } | 
 | 1176 |  | 
| Daniel Dunbar | d5f8a4f | 2008-09-03 21:13:56 +0000 | [diff] [blame] | 1177 | /// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr, | 
 | 1178 | /// int type). This simply type checks that type is one of the defined | 
 | 1179 | /// constants (0-3). | 
| Chris Lattner | fc8f0e1 | 2011-04-15 05:22:18 +0000 | [diff] [blame] | 1180 | // For compatibility check 0-3, llvm only handles 0 and 2. | 
| Daniel Dunbar | d5f8a4f | 2008-09-03 21:13:56 +0000 | [diff] [blame] | 1181 | bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) { | 
| Eric Christopher | 691ebc3 | 2010-04-17 02:26:23 +0000 | [diff] [blame] | 1182 |   llvm::APSInt Result; | 
 | 1183 |    | 
 | 1184 |   // Check constant-ness first. | 
 | 1185 |   if (SemaBuiltinConstantArg(TheCall, 1, Result)) | 
 | 1186 |     return true; | 
 | 1187 |  | 
| Daniel Dunbar | d5f8a4f | 2008-09-03 21:13:56 +0000 | [diff] [blame] | 1188 |   Expr *Arg = TheCall->getArg(1); | 
| Daniel Dunbar | d5f8a4f | 2008-09-03 21:13:56 +0000 | [diff] [blame] | 1189 |   if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1190 |     return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) | 
 | 1191 |              << "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); | 
| Daniel Dunbar | d5f8a4f | 2008-09-03 21:13:56 +0000 | [diff] [blame] | 1192 |   } | 
 | 1193 |  | 
 | 1194 |   return false; | 
 | 1195 | } | 
 | 1196 |  | 
| Eli Friedman | 586d6a8 | 2009-05-03 06:04:26 +0000 | [diff] [blame] | 1197 | /// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val). | 
| Eli Friedman | d875fed | 2009-05-03 04:46:36 +0000 | [diff] [blame] | 1198 | /// This checks that val is a constant 1. | 
 | 1199 | bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { | 
 | 1200 |   Expr *Arg = TheCall->getArg(1); | 
| Eric Christopher | 691ebc3 | 2010-04-17 02:26:23 +0000 | [diff] [blame] | 1201 |   llvm::APSInt Result; | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 1202 |  | 
| Eric Christopher | 691ebc3 | 2010-04-17 02:26:23 +0000 | [diff] [blame] | 1203 |   // TODO: This is less than ideal. Overload this to take a value. | 
 | 1204 |   if (SemaBuiltinConstantArg(TheCall, 1, Result)) | 
 | 1205 |     return true; | 
 | 1206 |    | 
 | 1207 |   if (Result != 1) | 
| Eli Friedman | d875fed | 2009-05-03 04:46:36 +0000 | [diff] [blame] | 1208 |     return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val) | 
 | 1209 |              << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); | 
 | 1210 |  | 
 | 1211 |   return false; | 
 | 1212 | } | 
 | 1213 |  | 
| Ted Kremenek | b43e8ad | 2011-02-24 23:03:04 +0000 | [diff] [blame] | 1214 | // Handle i > 1 ? "x" : "y", recursively. | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1215 | bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, | 
 | 1216 |                                   bool HasVAListArg, | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1217 |                                   unsigned format_idx, unsigned firstDataArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1218 |                                   bool isPrintf, bool inFunctionCall) { | 
| Ted Kremenek | 4fe6441 | 2010-09-09 03:51:39 +0000 | [diff] [blame] | 1219 |  tryAgain: | 
| Douglas Gregor | cde0173 | 2009-05-19 22:10:17 +0000 | [diff] [blame] | 1220 |   if (E->isTypeDependent() || E->isValueDependent()) | 
 | 1221 |     return false; | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1222 |  | 
| Peter Collingbourne | f111d93 | 2011-04-15 00:35:48 +0000 | [diff] [blame] | 1223 |   E = E->IgnoreParens(); | 
 | 1224 |  | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1225 |   switch (E->getStmtClass()) { | 
| John McCall | 56ca35d | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 1226 |   case Stmt::BinaryConditionalOperatorClass: | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1227 |   case Stmt::ConditionalOperatorClass: { | 
| John McCall | 56ca35d | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 1228 |     const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E); | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1229 |     return SemaCheckStringLiteral(C->getTrueExpr(), TheCall, HasVAListArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1230 |                                   format_idx, firstDataArg, isPrintf, | 
 | 1231 |                                   inFunctionCall) | 
| John McCall | 56ca35d | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 1232 |         && SemaCheckStringLiteral(C->getFalseExpr(), TheCall, HasVAListArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1233 |                                   format_idx, firstDataArg, isPrintf, | 
 | 1234 |                                   inFunctionCall); | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1235 |   } | 
 | 1236 |  | 
| Ted Kremenek | 95355bb | 2010-09-09 03:51:42 +0000 | [diff] [blame] | 1237 |   case Stmt::IntegerLiteralClass: | 
 | 1238 |     // Technically -Wformat-nonliteral does not warn about this case. | 
 | 1239 |     // The behavior of printf and friends in this case is implementation | 
 | 1240 |     // dependent.  Ideally if the format string cannot be null then | 
 | 1241 |     // it should have a 'nonnull' attribute in the function prototype. | 
 | 1242 |     return true; | 
 | 1243 |  | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1244 |   case Stmt::ImplicitCastExprClass: { | 
| Ted Kremenek | 4fe6441 | 2010-09-09 03:51:39 +0000 | [diff] [blame] | 1245 |     E = cast<ImplicitCastExpr>(E)->getSubExpr(); | 
 | 1246 |     goto tryAgain; | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1247 |   } | 
 | 1248 |  | 
| John McCall | 56ca35d | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 1249 |   case Stmt::OpaqueValueExprClass: | 
 | 1250 |     if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) { | 
 | 1251 |       E = src; | 
 | 1252 |       goto tryAgain; | 
 | 1253 |     } | 
 | 1254 |     return false; | 
 | 1255 |  | 
| Ted Kremenek | b43e8ad | 2011-02-24 23:03:04 +0000 | [diff] [blame] | 1256 |   case Stmt::PredefinedExprClass: | 
 | 1257 |     // While __func__, etc., are technically not string literals, they | 
 | 1258 |     // cannot contain format specifiers and thus are not a security | 
 | 1259 |     // liability. | 
 | 1260 |     return true; | 
 | 1261 |        | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1262 |   case Stmt::DeclRefExprClass: { | 
 | 1263 |     const DeclRefExpr *DR = cast<DeclRefExpr>(E); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1264 |  | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1265 |     // As an exception, do not flag errors for variables binding to | 
 | 1266 |     // const string literals. | 
 | 1267 |     if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { | 
 | 1268 |       bool isConstant = false; | 
 | 1269 |       QualType T = DR->getType(); | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1270 |  | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1271 |       if (const ArrayType *AT = Context.getAsArrayType(T)) { | 
 | 1272 |         isConstant = AT->getElementType().isConstant(Context); | 
| Mike Stump | ac5fc7c | 2009-08-04 21:02:39 +0000 | [diff] [blame] | 1273 |       } else if (const PointerType *PT = T->getAs<PointerType>()) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1274 |         isConstant = T.isConstant(Context) && | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1275 |                      PT->getPointeeType().isConstant(Context); | 
 | 1276 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1277 |  | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1278 |       if (isConstant) { | 
| Sebastian Redl | 31310a2 | 2010-02-01 20:16:42 +0000 | [diff] [blame] | 1279 |         if (const Expr *Init = VD->getAnyInitializer()) | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1280 |           return SemaCheckStringLiteral(Init, TheCall, | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1281 |                                         HasVAListArg, format_idx, firstDataArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1282 |                                         isPrintf, /*inFunctionCall*/false); | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1283 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1284 |  | 
| Anders Carlsson | d966a55 | 2009-06-28 19:55:58 +0000 | [diff] [blame] | 1285 |       // For vprintf* functions (i.e., HasVAListArg==true), we add a | 
 | 1286 |       // special check to see if the format string is a function parameter | 
 | 1287 |       // of the function calling the printf function.  If the function | 
 | 1288 |       // has an attribute indicating it is a printf-like function, then we | 
 | 1289 |       // should suppress warnings concerning non-literals being used in a call | 
 | 1290 |       // to a vprintf function.  For example: | 
 | 1291 |       // | 
 | 1292 |       // void | 
 | 1293 |       // logmessage(char const *fmt __attribute__ (format (printf, 1, 2)), ...){ | 
 | 1294 |       //      va_list ap; | 
 | 1295 |       //      va_start(ap, fmt); | 
 | 1296 |       //      vprintf(fmt, ap);  // Do NOT emit a warning about "fmt". | 
 | 1297 |       //      ... | 
 | 1298 |       // | 
 | 1299 |       // | 
 | 1300 |       //  FIXME: We don't have full attribute support yet, so just check to see | 
 | 1301 |       //    if the argument is a DeclRefExpr that references a parameter.  We'll | 
 | 1302 |       //    add proper support for checking the attribute later. | 
 | 1303 |       if (HasVAListArg) | 
 | 1304 |         if (isa<ParmVarDecl>(VD)) | 
 | 1305 |           return true; | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1306 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1307 |  | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1308 |     return false; | 
 | 1309 |   } | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1310 |  | 
| Anders Carlsson | 8f031b3 | 2009-06-27 04:05:33 +0000 | [diff] [blame] | 1311 |   case Stmt::CallExprClass: { | 
 | 1312 |     const CallExpr *CE = cast<CallExpr>(E); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1313 |     if (const ImplicitCastExpr *ICE | 
| Anders Carlsson | 8f031b3 | 2009-06-27 04:05:33 +0000 | [diff] [blame] | 1314 |           = dyn_cast<ImplicitCastExpr>(CE->getCallee())) { | 
 | 1315 |       if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) { | 
 | 1316 |         if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) { | 
| Argyrios Kyrtzidis | 40b598e | 2009-06-30 02:34:44 +0000 | [diff] [blame] | 1317 |           if (const FormatArgAttr *FA = FD->getAttr<FormatArgAttr>()) { | 
| Anders Carlsson | 8f031b3 | 2009-06-27 04:05:33 +0000 | [diff] [blame] | 1318 |             unsigned ArgIndex = FA->getFormatIdx(); | 
 | 1319 |             const Expr *Arg = CE->getArg(ArgIndex - 1); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1320 |  | 
 | 1321 |             return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1322 |                                           format_idx, firstDataArg, isPrintf, | 
 | 1323 |                                           inFunctionCall); | 
| Anders Carlsson | 8f031b3 | 2009-06-27 04:05:33 +0000 | [diff] [blame] | 1324 |           } | 
 | 1325 |         } | 
 | 1326 |       } | 
 | 1327 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1328 |  | 
| Anders Carlsson | 8f031b3 | 2009-06-27 04:05:33 +0000 | [diff] [blame] | 1329 |     return false; | 
 | 1330 |   } | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1331 |   case Stmt::ObjCStringLiteralClass: | 
 | 1332 |   case Stmt::StringLiteralClass: { | 
 | 1333 |     const StringLiteral *StrE = NULL; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1334 |  | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1335 |     if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E)) | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1336 |       StrE = ObjCFExpr->getString(); | 
 | 1337 |     else | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1338 |       StrE = cast<StringLiteral>(E); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1339 |  | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1340 |     if (StrE) { | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1341 |       CheckFormatString(StrE, E, TheCall, HasVAListArg, format_idx, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1342 |                         firstDataArg, isPrintf, inFunctionCall); | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1343 |       return true; | 
 | 1344 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1345 |  | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1346 |     return false; | 
 | 1347 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1348 |  | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1349 |   default: | 
 | 1350 |     return false; | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1351 |   } | 
 | 1352 | } | 
 | 1353 |  | 
| Fariborz Jahanian | e898f8a | 2009-05-21 18:48:51 +0000 | [diff] [blame] | 1354 | void | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1355 | Sema::CheckNonNullArguments(const NonNullAttr *NonNull, | 
| Nick Lewycky | 909a70d | 2011-03-25 01:44:32 +0000 | [diff] [blame] | 1356 |                             const Expr * const *ExprArgs, | 
 | 1357 |                             SourceLocation CallSiteLoc) { | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1358 |   for (NonNullAttr::args_iterator i = NonNull->args_begin(), | 
 | 1359 |                                   e = NonNull->args_end(); | 
| Fariborz Jahanian | e898f8a | 2009-05-21 18:48:51 +0000 | [diff] [blame] | 1360 |        i != e; ++i) { | 
| Nick Lewycky | 909a70d | 2011-03-25 01:44:32 +0000 | [diff] [blame] | 1361 |     const Expr *ArgExpr = ExprArgs[*i]; | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1362 |     if (ArgExpr->isNullPointerConstant(Context, | 
| Douglas Gregor | ce94049 | 2009-09-25 04:25:58 +0000 | [diff] [blame] | 1363 |                                        Expr::NPC_ValueDependentIsNotNull)) | 
| Nick Lewycky | 909a70d | 2011-03-25 01:44:32 +0000 | [diff] [blame] | 1364 |       Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); | 
| Fariborz Jahanian | e898f8a | 2009-05-21 18:48:51 +0000 | [diff] [blame] | 1365 |   } | 
 | 1366 | } | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1367 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1368 | /// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar | 
 | 1369 | /// functions) for correct use of format strings. | 
| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 1370 | void | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1371 | Sema::CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg, | 
 | 1372 |                                 unsigned format_idx, unsigned firstDataArg, | 
 | 1373 |                                 bool isPrintf) { | 
 | 1374 |  | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1375 |   const Expr *Fn = TheCall->getCallee(); | 
| Chris Lattner | 925e60d | 2007-12-28 05:29:59 +0000 | [diff] [blame] | 1376 |  | 
| Sebastian Redl | 4a2614e | 2009-11-17 18:02:24 +0000 | [diff] [blame] | 1377 |   // The way the format attribute works in GCC, the implicit this argument | 
 | 1378 |   // of member functions is counted. However, it doesn't appear in our own | 
 | 1379 |   // lists, so decrement format_idx in that case. | 
 | 1380 |   if (isa<CXXMemberCallExpr>(TheCall)) { | 
| Chandler Carruth | 9263a30 | 2010-11-16 08:49:43 +0000 | [diff] [blame] | 1381 |     const CXXMethodDecl *method_decl = | 
 | 1382 |       dyn_cast<CXXMethodDecl>(TheCall->getCalleeDecl()); | 
 | 1383 |     if (method_decl && method_decl->isInstance()) { | 
 | 1384 |       // Catch a format attribute mistakenly referring to the object argument. | 
 | 1385 |       if (format_idx == 0) | 
 | 1386 |         return; | 
 | 1387 |       --format_idx; | 
 | 1388 |       if(firstDataArg != 0) | 
 | 1389 |         --firstDataArg; | 
 | 1390 |     } | 
| Sebastian Redl | 4a2614e | 2009-11-17 18:02:24 +0000 | [diff] [blame] | 1391 |   } | 
 | 1392 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1393 |   // CHECK: printf/scanf-like function is called with no format string. | 
| Chris Lattner | 925e60d | 2007-12-28 05:29:59 +0000 | [diff] [blame] | 1394 |   if (format_idx >= TheCall->getNumArgs()) { | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1395 |     Diag(TheCall->getRParenLoc(), diag::warn_missing_format_string) | 
| Chris Lattner | dcd5ef1 | 2008-11-19 05:27:50 +0000 | [diff] [blame] | 1396 |       << Fn->getSourceRange(); | 
| Ted Kremenek | 71895b9 | 2007-08-14 17:39:48 +0000 | [diff] [blame] | 1397 |     return; | 
 | 1398 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1399 |  | 
| Ted Kremenek | 082d936 | 2009-03-20 21:35:28 +0000 | [diff] [blame] | 1400 |   const Expr *OrigFormatExpr = TheCall->getArg(format_idx)->IgnoreParenCasts(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1401 |  | 
| Chris Lattner | 59907c4 | 2007-08-10 20:18:51 +0000 | [diff] [blame] | 1402 |   // CHECK: format string is not a string literal. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1403 |   // | 
| Ted Kremenek | 71895b9 | 2007-08-14 17:39:48 +0000 | [diff] [blame] | 1404 |   // Dynamically generated format strings are difficult to | 
 | 1405 |   // automatically vet at compile time.  Requiring that format strings | 
 | 1406 |   // are string literals: (1) permits the checking of format strings by | 
 | 1407 |   // the compiler and thereby (2) can practically remove the source of | 
 | 1408 |   // many format string exploits. | 
| Ted Kremenek | 7ff22b2 | 2008-06-16 18:00:42 +0000 | [diff] [blame] | 1409 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1410 |   // Format string can be either ObjC string (e.g. @"%d") or | 
| Ted Kremenek | 7ff22b2 | 2008-06-16 18:00:42 +0000 | [diff] [blame] | 1411 |   // C string (e.g. "%d") | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1412 |   // ObjC string uses the same format specifiers as C string, so we can use | 
| Ted Kremenek | 7ff22b2 | 2008-06-16 18:00:42 +0000 | [diff] [blame] | 1413 |   // the same format string checking logic for both ObjC and C strings. | 
| Chris Lattner | 1cd3e1f | 2009-04-29 04:49:34 +0000 | [diff] [blame] | 1414 |   if (SemaCheckStringLiteral(OrigFormatExpr, TheCall, HasVAListArg, format_idx, | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1415 |                              firstDataArg, isPrintf)) | 
| Chris Lattner | 1cd3e1f | 2009-04-29 04:49:34 +0000 | [diff] [blame] | 1416 |     return;  // Literal format string found, check done! | 
| Ted Kremenek | 7ff22b2 | 2008-06-16 18:00:42 +0000 | [diff] [blame] | 1417 |  | 
| Chris Lattner | 655f141 | 2009-04-29 04:59:47 +0000 | [diff] [blame] | 1418 |   // If there are no arguments specified, warn with -Wformat-security, otherwise | 
 | 1419 |   // warn only with -Wformat-nonliteral. | 
 | 1420 |   if (TheCall->getNumArgs() == format_idx+1) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1421 |     Diag(TheCall->getArg(format_idx)->getLocStart(), | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1422 |          diag::warn_format_nonliteral_noargs) | 
| Chris Lattner | 655f141 | 2009-04-29 04:59:47 +0000 | [diff] [blame] | 1423 |       << OrigFormatExpr->getSourceRange(); | 
 | 1424 |   else | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1425 |     Diag(TheCall->getArg(format_idx)->getLocStart(), | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1426 |          diag::warn_format_nonliteral) | 
| Chris Lattner | 655f141 | 2009-04-29 04:59:47 +0000 | [diff] [blame] | 1427 |            << OrigFormatExpr->getSourceRange(); | 
| Ted Kremenek | d30ef87 | 2009-01-12 23:09:09 +0000 | [diff] [blame] | 1428 | } | 
| Ted Kremenek | 71895b9 | 2007-08-14 17:39:48 +0000 | [diff] [blame] | 1429 |  | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1430 | namespace { | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1431 | class CheckFormatHandler : public analyze_format_string::FormatStringHandler { | 
 | 1432 | protected: | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1433 |   Sema &S; | 
 | 1434 |   const StringLiteral *FExpr; | 
 | 1435 |   const Expr *OrigFormatExpr; | 
| Ted Kremenek | 6ee7653 | 2010-03-25 03:59:12 +0000 | [diff] [blame] | 1436 |   const unsigned FirstDataArg; | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1437 |   const unsigned NumDataArgs; | 
 | 1438 |   const bool IsObjCLiteral; | 
 | 1439 |   const char *Beg; // Start of format string. | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1440 |   const bool HasVAListArg; | 
 | 1441 |   const CallExpr *TheCall; | 
 | 1442 |   unsigned FormatIdx; | 
| Ted Kremenek | 7f70dc8 | 2010-02-26 19:18:41 +0000 | [diff] [blame] | 1443 |   llvm::BitVector CoveredArgs; | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 1444 |   bool usesPositionalArgs; | 
 | 1445 |   bool atFirstArg; | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1446 |   bool inFunctionCall; | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1447 | public: | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1448 |   CheckFormatHandler(Sema &s, const StringLiteral *fexpr, | 
| Ted Kremenek | 6ee7653 | 2010-03-25 03:59:12 +0000 | [diff] [blame] | 1449 |                      const Expr *origFormatExpr, unsigned firstDataArg, | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1450 |                      unsigned numDataArgs, bool isObjCLiteral, | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1451 |                      const char *beg, bool hasVAListArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1452 |                      const CallExpr *theCall, unsigned formatIdx, | 
 | 1453 |                      bool inFunctionCall) | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1454 |     : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), | 
| Ted Kremenek | 6ee7653 | 2010-03-25 03:59:12 +0000 | [diff] [blame] | 1455 |       FirstDataArg(firstDataArg), | 
| Ted Kremenek | 7f70dc8 | 2010-02-26 19:18:41 +0000 | [diff] [blame] | 1456 |       NumDataArgs(numDataArgs), | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1457 |       IsObjCLiteral(isObjCLiteral), Beg(beg), | 
 | 1458 |       HasVAListArg(hasVAListArg), | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 1459 |       TheCall(theCall), FormatIdx(formatIdx), | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1460 |       usesPositionalArgs(false), atFirstArg(true), | 
 | 1461 |       inFunctionCall(inFunctionCall) { | 
| Ted Kremenek | 7f70dc8 | 2010-02-26 19:18:41 +0000 | [diff] [blame] | 1462 |         CoveredArgs.resize(numDataArgs); | 
 | 1463 |         CoveredArgs.reset(); | 
 | 1464 |       } | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1465 |  | 
| Ted Kremenek | 07d161f | 2010-01-29 01:50:07 +0000 | [diff] [blame] | 1466 |   void DoneProcessing(); | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1467 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1468 |   void HandleIncompleteSpecifier(const char *startSpecifier, | 
 | 1469 |                                  unsigned specifierLen); | 
 | 1470 |      | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 1471 |   virtual void HandleInvalidPosition(const char *startSpecifier, | 
 | 1472 |                                      unsigned specifierLen, | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1473 |                                      analyze_format_string::PositionContext p); | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 1474 |  | 
 | 1475 |   virtual void HandleZeroPosition(const char *startPos, unsigned posLen); | 
 | 1476 |  | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1477 |   void HandleNullChar(const char *nullCharacter); | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1478 |  | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1479 |   template <typename Range> | 
 | 1480 |   static void EmitFormatDiagnostic(Sema &S, bool inFunctionCall, | 
 | 1481 |                                    const Expr *ArgumentExpr, | 
 | 1482 |                                    PartialDiagnostic PDiag, | 
 | 1483 |                                    SourceLocation StringLoc, | 
 | 1484 |                                    bool IsStringLocation, Range StringRange, | 
 | 1485 |                                    FixItHint Fixit = FixItHint()); | 
 | 1486 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1487 | protected: | 
| Ted Kremenek | c09b6a5 | 2010-07-19 21:25:57 +0000 | [diff] [blame] | 1488 |   bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc, | 
 | 1489 |                                         const char *startSpec, | 
 | 1490 |                                         unsigned specifierLen, | 
 | 1491 |                                         const char *csStart, unsigned csLen); | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1492 |  | 
 | 1493 |   void HandlePositionalNonpositionalArgs(SourceLocation Loc, | 
 | 1494 |                                          const char *startSpec, | 
 | 1495 |                                          unsigned specifierLen); | 
| Ted Kremenek | c09b6a5 | 2010-07-19 21:25:57 +0000 | [diff] [blame] | 1496 |    | 
| Ted Kremenek | f88c8e0 | 2010-01-29 20:55:36 +0000 | [diff] [blame] | 1497 |   SourceRange getFormatStringRange(); | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1498 |   CharSourceRange getSpecifierRange(const char *startSpecifier, | 
 | 1499 |                                     unsigned specifierLen); | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1500 |   SourceLocation getLocationOfByte(const char *x); | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1501 |  | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1502 |   const Expr *getDataArg(unsigned i) const; | 
| Ted Kremenek | 666a197 | 2010-07-26 19:45:42 +0000 | [diff] [blame] | 1503 |    | 
 | 1504 |   bool CheckNumArgs(const analyze_format_string::FormatSpecifier &FS, | 
 | 1505 |                     const analyze_format_string::ConversionSpecifier &CS, | 
 | 1506 |                     const char *startSpecifier, unsigned specifierLen, | 
 | 1507 |                     unsigned argIndex); | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1508 |  | 
 | 1509 |   template <typename Range> | 
 | 1510 |   void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc, | 
 | 1511 |                             bool IsStringLocation, Range StringRange, | 
 | 1512 |                             FixItHint Fixit = FixItHint()); | 
 | 1513 |  | 
 | 1514 |   void CheckPositionalAndNonpositionalArgs( | 
 | 1515 |       const analyze_format_string::FormatSpecifier *FS); | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1516 | }; | 
 | 1517 | } | 
 | 1518 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1519 | SourceRange CheckFormatHandler::getFormatStringRange() { | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1520 |   return OrigFormatExpr->getSourceRange(); | 
 | 1521 | } | 
 | 1522 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1523 | CharSourceRange CheckFormatHandler:: | 
 | 1524 | getSpecifierRange(const char *startSpecifier, unsigned specifierLen) { | 
| Tom Care | 45f9b7e | 2010-06-21 21:21:01 +0000 | [diff] [blame] | 1525 |   SourceLocation Start = getLocationOfByte(startSpecifier); | 
 | 1526 |   SourceLocation End   = getLocationOfByte(startSpecifier + specifierLen - 1); | 
 | 1527 |  | 
 | 1528 |   // Advance the end SourceLocation by one due to half-open ranges. | 
| Argyrios Kyrtzidis | a64ccef | 2011-09-19 20:40:19 +0000 | [diff] [blame] | 1529 |   End = End.getLocWithOffset(1); | 
| Tom Care | 45f9b7e | 2010-06-21 21:21:01 +0000 | [diff] [blame] | 1530 |  | 
 | 1531 |   return CharSourceRange::getCharRange(Start, End); | 
| Ted Kremenek | f88c8e0 | 2010-01-29 20:55:36 +0000 | [diff] [blame] | 1532 | } | 
 | 1533 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1534 | SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) { | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1535 |   return S.getLocationOfStringLiteralByte(FExpr, x - Beg); | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1536 | } | 
 | 1537 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1538 | void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier, | 
 | 1539 |                                                    unsigned specifierLen){ | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1540 |   EmitFormatDiagnostic(S.PDiag(diag::warn_printf_incomplete_specifier), | 
 | 1541 |                        getLocationOfByte(startSpecifier), | 
 | 1542 |                        /*IsStringLocation*/true, | 
 | 1543 |                        getSpecifierRange(startSpecifier, specifierLen)); | 
| Ted Kremenek | 808015a | 2010-01-29 03:16:21 +0000 | [diff] [blame] | 1544 | } | 
 | 1545 |  | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 1546 | void | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1547 | CheckFormatHandler::HandleInvalidPosition(const char *startPos, unsigned posLen, | 
 | 1548 |                                      analyze_format_string::PositionContext p) { | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1549 |   EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_positional_specifier) | 
 | 1550 |                          << (unsigned) p, | 
 | 1551 |                        getLocationOfByte(startPos), /*IsStringLocation*/true, | 
 | 1552 |                        getSpecifierRange(startPos, posLen)); | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 1553 | } | 
 | 1554 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1555 | void CheckFormatHandler::HandleZeroPosition(const char *startPos, | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 1556 |                                             unsigned posLen) { | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1557 |   EmitFormatDiagnostic(S.PDiag(diag::warn_format_zero_positional_specifier), | 
 | 1558 |                                getLocationOfByte(startPos), | 
 | 1559 |                                /*IsStringLocation*/true, | 
 | 1560 |                                getSpecifierRange(startPos, posLen)); | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 1561 | } | 
 | 1562 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1563 | void CheckFormatHandler::HandleNullChar(const char *nullCharacter) { | 
| Ted Kremenek | 0c06944 | 2011-03-15 21:18:48 +0000 | [diff] [blame] | 1564 |   if (!IsObjCLiteral) { | 
 | 1565 |     // The presence of a null character is likely an error. | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1566 |     EmitFormatDiagnostic( | 
 | 1567 |       S.PDiag(diag::warn_printf_format_string_contains_null_char), | 
 | 1568 |       getLocationOfByte(nullCharacter), /*IsStringLocation*/true, | 
 | 1569 |       getFormatStringRange()); | 
| Ted Kremenek | 0c06944 | 2011-03-15 21:18:48 +0000 | [diff] [blame] | 1570 |   } | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1571 | } | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1572 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1573 | const Expr *CheckFormatHandler::getDataArg(unsigned i) const { | 
 | 1574 |   return TheCall->getArg(FirstDataArg + i); | 
 | 1575 | } | 
 | 1576 |  | 
 | 1577 | void CheckFormatHandler::DoneProcessing() { | 
 | 1578 |     // Does the number of data arguments exceed the number of | 
 | 1579 |     // format conversions in the format string? | 
 | 1580 |   if (!HasVAListArg) { | 
 | 1581 |       // Find any arguments that weren't covered. | 
 | 1582 |     CoveredArgs.flip(); | 
 | 1583 |     signed notCoveredArg = CoveredArgs.find_first(); | 
 | 1584 |     if (notCoveredArg >= 0) { | 
 | 1585 |       assert((unsigned)notCoveredArg < NumDataArgs); | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1586 |       EmitFormatDiagnostic(S.PDiag(diag::warn_printf_data_arg_not_used), | 
 | 1587 |                            getDataArg((unsigned) notCoveredArg)->getLocStart(), | 
 | 1588 |                            /*IsStringLocation*/false, getFormatStringRange()); | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1589 |     } | 
 | 1590 |   } | 
 | 1591 | } | 
 | 1592 |  | 
| Ted Kremenek | c09b6a5 | 2010-07-19 21:25:57 +0000 | [diff] [blame] | 1593 | bool | 
 | 1594 | CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex, | 
 | 1595 |                                                      SourceLocation Loc, | 
 | 1596 |                                                      const char *startSpec, | 
 | 1597 |                                                      unsigned specifierLen, | 
 | 1598 |                                                      const char *csStart, | 
 | 1599 |                                                      unsigned csLen) { | 
 | 1600 |    | 
 | 1601 |   bool keepGoing = true; | 
 | 1602 |   if (argIndex < NumDataArgs) { | 
 | 1603 |     // Consider the argument coverered, even though the specifier doesn't | 
 | 1604 |     // make sense. | 
 | 1605 |     CoveredArgs.set(argIndex); | 
 | 1606 |   } | 
 | 1607 |   else { | 
 | 1608 |     // If argIndex exceeds the number of data arguments we | 
 | 1609 |     // don't issue a warning because that is just a cascade of warnings (and | 
 | 1610 |     // they may have intended '%%' anyway). We don't want to continue processing | 
 | 1611 |     // the format string after this point, however, as we will like just get | 
 | 1612 |     // gibberish when trying to match arguments. | 
 | 1613 |     keepGoing = false; | 
 | 1614 |   } | 
 | 1615 |    | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1616 |   EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_conversion) | 
 | 1617 |                          << StringRef(csStart, csLen), | 
 | 1618 |                        Loc, /*IsStringLocation*/true, | 
 | 1619 |                        getSpecifierRange(startSpec, specifierLen)); | 
| Ted Kremenek | c09b6a5 | 2010-07-19 21:25:57 +0000 | [diff] [blame] | 1620 |    | 
 | 1621 |   return keepGoing; | 
 | 1622 | } | 
 | 1623 |  | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1624 | void | 
 | 1625 | CheckFormatHandler::HandlePositionalNonpositionalArgs(SourceLocation Loc, | 
 | 1626 |                                                       const char *startSpec, | 
 | 1627 |                                                       unsigned specifierLen) { | 
 | 1628 |   EmitFormatDiagnostic( | 
 | 1629 |     S.PDiag(diag::warn_format_mix_positional_nonpositional_args), | 
 | 1630 |     Loc, /*isStringLoc*/true, getSpecifierRange(startSpec, specifierLen)); | 
 | 1631 | } | 
 | 1632 |  | 
| Ted Kremenek | 666a197 | 2010-07-26 19:45:42 +0000 | [diff] [blame] | 1633 | bool | 
 | 1634 | CheckFormatHandler::CheckNumArgs( | 
 | 1635 |   const analyze_format_string::FormatSpecifier &FS, | 
 | 1636 |   const analyze_format_string::ConversionSpecifier &CS, | 
 | 1637 |   const char *startSpecifier, unsigned specifierLen, unsigned argIndex) { | 
 | 1638 |  | 
 | 1639 |   if (argIndex >= NumDataArgs) { | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1640 |     PartialDiagnostic PDiag = FS.usesPositionalArg() | 
 | 1641 |       ? (S.PDiag(diag::warn_printf_positional_arg_exceeds_data_args) | 
 | 1642 |            << (argIndex+1) << NumDataArgs) | 
 | 1643 |       : S.PDiag(diag::warn_printf_insufficient_data_args); | 
 | 1644 |     EmitFormatDiagnostic( | 
 | 1645 |       PDiag, getLocationOfByte(CS.getStart()), /*IsStringLocation*/true, | 
 | 1646 |       getSpecifierRange(startSpecifier, specifierLen)); | 
| Ted Kremenek | 666a197 | 2010-07-26 19:45:42 +0000 | [diff] [blame] | 1647 |     return false; | 
 | 1648 |   } | 
 | 1649 |   return true; | 
 | 1650 | } | 
 | 1651 |  | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1652 | template<typename Range> | 
 | 1653 | void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag, | 
 | 1654 |                                               SourceLocation Loc, | 
 | 1655 |                                               bool IsStringLocation, | 
 | 1656 |                                               Range StringRange, | 
 | 1657 |                                               FixItHint FixIt) { | 
 | 1658 |   EmitFormatDiagnostic(S, inFunctionCall, TheCall->getArg(FormatIdx), PDiag, | 
 | 1659 |                        Loc, IsStringLocation, StringRange, FixIt); | 
 | 1660 | } | 
 | 1661 |  | 
 | 1662 | /// \brief If the format string is not within the funcion call, emit a note | 
 | 1663 | /// so that the function call and string are in diagnostic messages. | 
 | 1664 | /// | 
 | 1665 | /// \param inFunctionCall if true, the format string is within the function | 
 | 1666 | /// call and only one diagnostic message will be produced.  Otherwise, an | 
 | 1667 | /// extra note will be emitted pointing to location of the format string. | 
 | 1668 | /// | 
 | 1669 | /// \param ArgumentExpr the expression that is passed as the format string | 
 | 1670 | /// argument in the function call.  Used for getting locations when two | 
 | 1671 | /// diagnostics are emitted. | 
 | 1672 | /// | 
 | 1673 | /// \param PDiag the callee should already have provided any strings for the | 
 | 1674 | /// diagnostic message.  This function only adds locations and fixits | 
 | 1675 | /// to diagnostics. | 
 | 1676 | /// | 
 | 1677 | /// \param Loc primary location for diagnostic.  If two diagnostics are | 
 | 1678 | /// required, one will be at Loc and a new SourceLocation will be created for | 
 | 1679 | /// the other one. | 
 | 1680 | /// | 
 | 1681 | /// \param IsStringLocation if true, Loc points to the format string should be | 
 | 1682 | /// used for the note.  Otherwise, Loc points to the argument list and will | 
 | 1683 | /// be used with PDiag. | 
 | 1684 | /// | 
 | 1685 | /// \param StringRange some or all of the string to highlight.  This is | 
 | 1686 | /// templated so it can accept either a CharSourceRange or a SourceRange. | 
 | 1687 | /// | 
 | 1688 | /// \param Fixit optional fix it hint for the format string. | 
 | 1689 | template<typename Range> | 
 | 1690 | void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall, | 
 | 1691 |                                               const Expr *ArgumentExpr, | 
 | 1692 |                                               PartialDiagnostic PDiag, | 
 | 1693 |                                               SourceLocation Loc, | 
 | 1694 |                                               bool IsStringLocation, | 
 | 1695 |                                               Range StringRange, | 
 | 1696 |                                               FixItHint FixIt) { | 
 | 1697 |   if (InFunctionCall) | 
 | 1698 |     S.Diag(Loc, PDiag) << StringRange << FixIt; | 
 | 1699 |   else { | 
 | 1700 |     S.Diag(IsStringLocation ? ArgumentExpr->getExprLoc() : Loc, PDiag) | 
 | 1701 |       << ArgumentExpr->getSourceRange(); | 
 | 1702 |     S.Diag(IsStringLocation ? Loc : StringRange.getBegin(), | 
 | 1703 |            diag::note_format_string_defined) | 
 | 1704 |       << StringRange << FixIt; | 
 | 1705 |   } | 
 | 1706 | } | 
 | 1707 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1708 | //===--- CHECK: Printf format string checking ------------------------------===// | 
 | 1709 |  | 
 | 1710 | namespace { | 
 | 1711 | class CheckPrintfHandler : public CheckFormatHandler { | 
 | 1712 | public: | 
 | 1713 |   CheckPrintfHandler(Sema &s, const StringLiteral *fexpr, | 
 | 1714 |                      const Expr *origFormatExpr, unsigned firstDataArg, | 
 | 1715 |                      unsigned numDataArgs, bool isObjCLiteral, | 
 | 1716 |                      const char *beg, bool hasVAListArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1717 |                      const CallExpr *theCall, unsigned formatIdx, | 
 | 1718 |                      bool inFunctionCall) | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1719 |   : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, | 
 | 1720 |                        numDataArgs, isObjCLiteral, beg, hasVAListArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1721 |                        theCall, formatIdx, inFunctionCall) {} | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1722 |    | 
 | 1723 |    | 
 | 1724 |   bool HandleInvalidPrintfConversionSpecifier( | 
 | 1725 |                                       const analyze_printf::PrintfSpecifier &FS, | 
 | 1726 |                                       const char *startSpecifier, | 
 | 1727 |                                       unsigned specifierLen); | 
 | 1728 |    | 
 | 1729 |   bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, | 
 | 1730 |                              const char *startSpecifier, | 
 | 1731 |                              unsigned specifierLen); | 
 | 1732 |    | 
 | 1733 |   bool HandleAmount(const analyze_format_string::OptionalAmount &Amt, unsigned k, | 
 | 1734 |                     const char *startSpecifier, unsigned specifierLen); | 
 | 1735 |   void HandleInvalidAmount(const analyze_printf::PrintfSpecifier &FS, | 
 | 1736 |                            const analyze_printf::OptionalAmount &Amt, | 
 | 1737 |                            unsigned type, | 
 | 1738 |                            const char *startSpecifier, unsigned specifierLen); | 
 | 1739 |   void HandleFlag(const analyze_printf::PrintfSpecifier &FS, | 
 | 1740 |                   const analyze_printf::OptionalFlag &flag, | 
 | 1741 |                   const char *startSpecifier, unsigned specifierLen); | 
 | 1742 |   void HandleIgnoredFlag(const analyze_printf::PrintfSpecifier &FS, | 
 | 1743 |                          const analyze_printf::OptionalFlag &ignoredFlag, | 
 | 1744 |                          const analyze_printf::OptionalFlag &flag, | 
 | 1745 |                          const char *startSpecifier, unsigned specifierLen); | 
 | 1746 | };   | 
 | 1747 | } | 
 | 1748 |  | 
 | 1749 | bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier( | 
 | 1750 |                                       const analyze_printf::PrintfSpecifier &FS, | 
 | 1751 |                                       const char *startSpecifier, | 
 | 1752 |                                       unsigned specifierLen) { | 
| Ted Kremenek | 6ecb950 | 2010-07-20 20:04:27 +0000 | [diff] [blame] | 1753 |   const analyze_printf::PrintfConversionSpecifier &CS = | 
| Ted Kremenek | c09b6a5 | 2010-07-19 21:25:57 +0000 | [diff] [blame] | 1754 |     FS.getConversionSpecifier(); | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1755 |    | 
| Ted Kremenek | c09b6a5 | 2010-07-19 21:25:57 +0000 | [diff] [blame] | 1756 |   return HandleInvalidConversionSpecifier(FS.getArgIndex(), | 
 | 1757 |                                           getLocationOfByte(CS.getStart()), | 
 | 1758 |                                           startSpecifier, specifierLen, | 
 | 1759 |                                           CS.getStart(), CS.getLength()); | 
| Ted Kremenek | 26ac2e0 | 2010-01-29 02:40:24 +0000 | [diff] [blame] | 1760 | } | 
 | 1761 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1762 | bool CheckPrintfHandler::HandleAmount( | 
 | 1763 |                                const analyze_format_string::OptionalAmount &Amt, | 
 | 1764 |                                unsigned k, const char *startSpecifier, | 
 | 1765 |                                unsigned specifierLen) { | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1766 |  | 
 | 1767 |   if (Amt.hasDataArgument()) { | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1768 |     if (!HasVAListArg) { | 
| Ted Kremenek | 7f70dc8 | 2010-02-26 19:18:41 +0000 | [diff] [blame] | 1769 |       unsigned argIndex = Amt.getArgIndex(); | 
 | 1770 |       if (argIndex >= NumDataArgs) { | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1771 |         EmitFormatDiagnostic(S.PDiag(diag::warn_printf_asterisk_missing_arg) | 
 | 1772 |                                << k, | 
 | 1773 |                              getLocationOfByte(Amt.getStart()), | 
 | 1774 |                              /*IsStringLocation*/true, | 
 | 1775 |                              getSpecifierRange(startSpecifier, specifierLen)); | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1776 |         // Don't do any more checking.  We will just emit | 
 | 1777 |         // spurious errors. | 
 | 1778 |         return false; | 
 | 1779 |       } | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1780 |  | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1781 |       // Type check the data argument.  It should be an 'int'. | 
| Ted Kremenek | 31f8e32 | 2010-01-29 23:32:22 +0000 | [diff] [blame] | 1782 |       // Although not in conformance with C99, we also allow the argument to be | 
 | 1783 |       // an 'unsigned int' as that is a reasonably safe case.  GCC also | 
 | 1784 |       // doesn't emit a warning for that case. | 
| Ted Kremenek | 7f70dc8 | 2010-02-26 19:18:41 +0000 | [diff] [blame] | 1785 |       CoveredArgs.set(argIndex); | 
 | 1786 |       const Expr *Arg = getDataArg(argIndex); | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1787 |       QualType T = Arg->getType(); | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1788 |  | 
 | 1789 |       const analyze_printf::ArgTypeResult &ATR = Amt.getArgType(S.Context); | 
 | 1790 |       assert(ATR.isValid()); | 
 | 1791 |  | 
 | 1792 |       if (!ATR.matchesType(S.Context, T)) { | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1793 |         EmitFormatDiagnostic(S.PDiag(diag::warn_printf_asterisk_wrong_type) | 
 | 1794 |                                << k << ATR.getRepresentativeType(S.Context) | 
 | 1795 |                                << T << Arg->getSourceRange(), | 
 | 1796 |                              getLocationOfByte(Amt.getStart()), | 
 | 1797 |                              /*IsStringLocation*/true, | 
 | 1798 |                              getSpecifierRange(startSpecifier, specifierLen)); | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1799 |         // Don't do any more checking.  We will just emit | 
 | 1800 |         // spurious errors. | 
 | 1801 |         return false; | 
 | 1802 |       } | 
 | 1803 |     } | 
 | 1804 |   } | 
 | 1805 |   return true; | 
 | 1806 | } | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1807 |  | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1808 | void CheckPrintfHandler::HandleInvalidAmount( | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1809 |                                       const analyze_printf::PrintfSpecifier &FS, | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1810 |                                       const analyze_printf::OptionalAmount &Amt, | 
 | 1811 |                                       unsigned type, | 
 | 1812 |                                       const char *startSpecifier, | 
 | 1813 |                                       unsigned specifierLen) { | 
| Ted Kremenek | 6ecb950 | 2010-07-20 20:04:27 +0000 | [diff] [blame] | 1814 |   const analyze_printf::PrintfConversionSpecifier &CS = | 
 | 1815 |     FS.getConversionSpecifier(); | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1816 |  | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1817 |   FixItHint fixit = | 
 | 1818 |     Amt.getHowSpecified() == analyze_printf::OptionalAmount::Constant | 
 | 1819 |       ? FixItHint::CreateRemoval(getSpecifierRange(Amt.getStart(), | 
 | 1820 |                                  Amt.getConstantLength())) | 
 | 1821 |       : FixItHint(); | 
 | 1822 |  | 
 | 1823 |   EmitFormatDiagnostic(S.PDiag(diag::warn_printf_nonsensical_optional_amount) | 
 | 1824 |                          << type << CS.toString(), | 
 | 1825 |                        getLocationOfByte(Amt.getStart()), | 
 | 1826 |                        /*IsStringLocation*/true, | 
 | 1827 |                        getSpecifierRange(startSpecifier, specifierLen), | 
 | 1828 |                        fixit); | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1829 | } | 
 | 1830 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1831 | void CheckPrintfHandler::HandleFlag(const analyze_printf::PrintfSpecifier &FS, | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1832 |                                     const analyze_printf::OptionalFlag &flag, | 
 | 1833 |                                     const char *startSpecifier, | 
 | 1834 |                                     unsigned specifierLen) { | 
 | 1835 |   // Warn about pointless flag with a fixit removal. | 
| Ted Kremenek | 6ecb950 | 2010-07-20 20:04:27 +0000 | [diff] [blame] | 1836 |   const analyze_printf::PrintfConversionSpecifier &CS = | 
 | 1837 |     FS.getConversionSpecifier(); | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1838 |   EmitFormatDiagnostic(S.PDiag(diag::warn_printf_nonsensical_flag) | 
 | 1839 |                          << flag.toString() << CS.toString(), | 
 | 1840 |                        getLocationOfByte(flag.getPosition()), | 
 | 1841 |                        /*IsStringLocation*/true, | 
 | 1842 |                        getSpecifierRange(startSpecifier, specifierLen), | 
 | 1843 |                        FixItHint::CreateRemoval( | 
 | 1844 |                          getSpecifierRange(flag.getPosition(), 1))); | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1845 | } | 
 | 1846 |  | 
 | 1847 | void CheckPrintfHandler::HandleIgnoredFlag( | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1848 |                                 const analyze_printf::PrintfSpecifier &FS, | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1849 |                                 const analyze_printf::OptionalFlag &ignoredFlag, | 
 | 1850 |                                 const analyze_printf::OptionalFlag &flag, | 
 | 1851 |                                 const char *startSpecifier, | 
 | 1852 |                                 unsigned specifierLen) { | 
 | 1853 |   // Warn about ignored flag with a fixit removal. | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1854 |   EmitFormatDiagnostic(S.PDiag(diag::warn_printf_ignored_flag) | 
 | 1855 |                          << ignoredFlag.toString() << flag.toString(), | 
 | 1856 |                        getLocationOfByte(ignoredFlag.getPosition()), | 
 | 1857 |                        /*IsStringLocation*/true, | 
 | 1858 |                        getSpecifierRange(startSpecifier, specifierLen), | 
 | 1859 |                        FixItHint::CreateRemoval( | 
 | 1860 |                          getSpecifierRange(ignoredFlag.getPosition(), 1))); | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1861 | } | 
 | 1862 |  | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1863 | bool | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1864 | CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier | 
| Ted Kremenek | 5c41ee8 | 2010-02-11 09:27:41 +0000 | [diff] [blame] | 1865 |                                             &FS, | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1866 |                                           const char *startSpecifier, | 
 | 1867 |                                           unsigned specifierLen) { | 
 | 1868 |  | 
| Ted Kremenek | 6ecb950 | 2010-07-20 20:04:27 +0000 | [diff] [blame] | 1869 |   using namespace analyze_format_string; | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 1870 |   using namespace analyze_printf;   | 
| Ted Kremenek | 6ecb950 | 2010-07-20 20:04:27 +0000 | [diff] [blame] | 1871 |   const PrintfConversionSpecifier &CS = FS.getConversionSpecifier(); | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 1872 |  | 
| Ted Kremenek | baa4006 | 2010-07-19 22:01:06 +0000 | [diff] [blame] | 1873 |   if (FS.consumesDataArgument()) { | 
 | 1874 |     if (atFirstArg) { | 
 | 1875 |         atFirstArg = false; | 
 | 1876 |         usesPositionalArgs = FS.usesPositionalArg(); | 
 | 1877 |     } | 
 | 1878 |     else if (usesPositionalArgs != FS.usesPositionalArg()) { | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1879 |       HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()), | 
 | 1880 |                                         startSpecifier, specifierLen); | 
| Ted Kremenek | baa4006 | 2010-07-19 22:01:06 +0000 | [diff] [blame] | 1881 |       return false; | 
 | 1882 |     } | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1883 |   } | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1884 |  | 
| Ted Kremenek | efaff19 | 2010-02-27 01:41:03 +0000 | [diff] [blame] | 1885 |   // First check if the field width, precision, and conversion specifier | 
 | 1886 |   // have matching data arguments. | 
 | 1887 |   if (!HandleAmount(FS.getFieldWidth(), /* field width */ 0, | 
 | 1888 |                     startSpecifier, specifierLen)) { | 
 | 1889 |     return false; | 
 | 1890 |   } | 
 | 1891 |  | 
 | 1892 |   if (!HandleAmount(FS.getPrecision(), /* precision */ 1, | 
 | 1893 |                     startSpecifier, specifierLen)) { | 
| Ted Kremenek | 0d27735 | 2010-01-29 01:06:55 +0000 | [diff] [blame] | 1894 |     return false; | 
 | 1895 |   } | 
 | 1896 |  | 
| Ted Kremenek | f88c8e0 | 2010-01-29 20:55:36 +0000 | [diff] [blame] | 1897 |   if (!CS.consumesDataArgument()) { | 
 | 1898 |     // FIXME: Technically specifying a precision or field width here | 
 | 1899 |     // makes no sense.  Worth issuing a warning at some point. | 
| Ted Kremenek | 0e5675d | 2010-02-10 02:16:30 +0000 | [diff] [blame] | 1900 |     return true; | 
| Ted Kremenek | f88c8e0 | 2010-01-29 20:55:36 +0000 | [diff] [blame] | 1901 |   } | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1902 |  | 
| Ted Kremenek | 7f70dc8 | 2010-02-26 19:18:41 +0000 | [diff] [blame] | 1903 |   // Consume the argument. | 
 | 1904 |   unsigned argIndex = FS.getArgIndex(); | 
| Ted Kremenek | e3fc547 | 2010-02-27 08:34:51 +0000 | [diff] [blame] | 1905 |   if (argIndex < NumDataArgs) { | 
 | 1906 |     // The check to see if the argIndex is valid will come later. | 
 | 1907 |     // We set the bit here because we may exit early from this | 
 | 1908 |     // function if we encounter some other error. | 
 | 1909 |     CoveredArgs.set(argIndex); | 
 | 1910 |   } | 
| Ted Kremenek | 7f70dc8 | 2010-02-26 19:18:41 +0000 | [diff] [blame] | 1911 |  | 
 | 1912 |   // Check for using an Objective-C specific conversion specifier | 
 | 1913 |   // in a non-ObjC literal. | 
 | 1914 |   if (!IsObjCLiteral && CS.isObjCArg()) { | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 1915 |     return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier, | 
 | 1916 |                                                   specifierLen); | 
| Ted Kremenek | 7f70dc8 | 2010-02-26 19:18:41 +0000 | [diff] [blame] | 1917 |   } | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1918 |  | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1919 |   // Check for invalid use of field width | 
 | 1920 |   if (!FS.hasValidFieldWidth()) { | 
| Tom Care | 45f9b7e | 2010-06-21 21:21:01 +0000 | [diff] [blame] | 1921 |     HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0, | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1922 |         startSpecifier, specifierLen); | 
 | 1923 |   } | 
 | 1924 |  | 
 | 1925 |   // Check for invalid use of precision | 
 | 1926 |   if (!FS.hasValidPrecision()) { | 
 | 1927 |     HandleInvalidAmount(FS, FS.getPrecision(), /* precision */ 1, | 
 | 1928 |         startSpecifier, specifierLen); | 
 | 1929 |   } | 
 | 1930 |  | 
 | 1931 |   // Check each flag does not conflict with any other component. | 
| Ted Kremenek | 65197b4 | 2011-01-08 05:28:46 +0000 | [diff] [blame] | 1932 |   if (!FS.hasValidThousandsGroupingPrefix()) | 
 | 1933 |     HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen); | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1934 |   if (!FS.hasValidLeadingZeros()) | 
 | 1935 |     HandleFlag(FS, FS.hasLeadingZeros(), startSpecifier, specifierLen); | 
 | 1936 |   if (!FS.hasValidPlusPrefix()) | 
 | 1937 |     HandleFlag(FS, FS.hasPlusPrefix(), startSpecifier, specifierLen); | 
| Tom Care | 45f9b7e | 2010-06-21 21:21:01 +0000 | [diff] [blame] | 1938 |   if (!FS.hasValidSpacePrefix()) | 
 | 1939 |     HandleFlag(FS, FS.hasSpacePrefix(), startSpecifier, specifierLen); | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1940 |   if (!FS.hasValidAlternativeForm()) | 
 | 1941 |     HandleFlag(FS, FS.hasAlternativeForm(), startSpecifier, specifierLen); | 
 | 1942 |   if (!FS.hasValidLeftJustified()) | 
 | 1943 |     HandleFlag(FS, FS.isLeftJustified(), startSpecifier, specifierLen); | 
 | 1944 |  | 
 | 1945 |   // Check that flags are not ignored by another flag | 
| Tom Care | 45f9b7e | 2010-06-21 21:21:01 +0000 | [diff] [blame] | 1946 |   if (FS.hasSpacePrefix() && FS.hasPlusPrefix()) // ' ' ignored by '+' | 
 | 1947 |     HandleIgnoredFlag(FS, FS.hasSpacePrefix(), FS.hasPlusPrefix(), | 
 | 1948 |         startSpecifier, specifierLen); | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1949 |   if (FS.hasLeadingZeros() && FS.isLeftJustified()) // '0' ignored by '-' | 
 | 1950 |     HandleIgnoredFlag(FS, FS.hasLeadingZeros(), FS.isLeftJustified(), | 
 | 1951 |             startSpecifier, specifierLen); | 
 | 1952 |  | 
 | 1953 |   // Check the length modifier is valid with the given conversion specifier. | 
 | 1954 |   const LengthModifier &LM = FS.getLengthModifier(); | 
 | 1955 |   if (!FS.hasValidLengthModifier()) | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1956 |     EmitFormatDiagnostic(S.PDiag(diag::warn_format_nonsensical_length) | 
 | 1957 |                            << LM.toString() << CS.toString(), | 
 | 1958 |                          getLocationOfByte(LM.getStart()), | 
 | 1959 |                          /*IsStringLocation*/true, | 
 | 1960 |                          getSpecifierRange(startSpecifier, specifierLen), | 
 | 1961 |                          FixItHint::CreateRemoval( | 
 | 1962 |                            getSpecifierRange(LM.getStart(), | 
 | 1963 |                                              LM.getLength()))); | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1964 |  | 
 | 1965 |   // Are we using '%n'? | 
| Ted Kremenek | 35d353b | 2010-07-20 20:04:10 +0000 | [diff] [blame] | 1966 |   if (CS.getKind() == ConversionSpecifier::nArg) { | 
| Tom Care | e4ee966 | 2010-06-17 19:00:27 +0000 | [diff] [blame] | 1967 |     // Issue a warning about this being a possible security issue. | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 1968 |     EmitFormatDiagnostic(S.PDiag(diag::warn_printf_write_back), | 
 | 1969 |                          getLocationOfByte(CS.getStart()), | 
 | 1970 |                          /*IsStringLocation*/true, | 
 | 1971 |                          getSpecifierRange(startSpecifier, specifierLen)); | 
| Ted Kremenek | e82d804 | 2010-01-29 01:35:25 +0000 | [diff] [blame] | 1972 |     // Continue checking the other format specifiers. | 
 | 1973 |     return true; | 
 | 1974 |   } | 
| Ted Kremenek | 5c41ee8 | 2010-02-11 09:27:41 +0000 | [diff] [blame] | 1975 |  | 
| Ted Kremenek | da51f0d | 2010-01-29 01:43:31 +0000 | [diff] [blame] | 1976 |   // The remaining checks depend on the data arguments. | 
 | 1977 |   if (HasVAListArg) | 
 | 1978 |     return true; | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1979 |  | 
| Ted Kremenek | 666a197 | 2010-07-26 19:45:42 +0000 | [diff] [blame] | 1980 |   if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) | 
| Ted Kremenek | da51f0d | 2010-01-29 01:43:31 +0000 | [diff] [blame] | 1981 |     return false; | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 1982 |  | 
| Michael J. Spencer | 96827eb | 2010-07-27 04:46:02 +0000 | [diff] [blame] | 1983 |   // Now type check the data expression that matches the | 
 | 1984 |   // format specifier. | 
 | 1985 |   const Expr *Ex = getDataArg(argIndex); | 
 | 1986 |   const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context); | 
 | 1987 |   if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) { | 
 | 1988 |     // Check if we didn't match because of an implicit cast from a 'char' | 
 | 1989 |     // or 'short' to an 'int'.  This is done because printf is a varargs | 
 | 1990 |     // function. | 
 | 1991 |     if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex)) | 
| Ted Kremenek | 4d8ae4d | 2010-10-21 04:00:58 +0000 | [diff] [blame] | 1992 |       if (ICE->getType() == S.Context.IntTy) { | 
 | 1993 |         // All further checking is done on the subexpression. | 
 | 1994 |         Ex = ICE->getSubExpr(); | 
 | 1995 |         if (ATR.matchesType(S.Context, Ex->getType())) | 
| Michael J. Spencer | 96827eb | 2010-07-27 04:46:02 +0000 | [diff] [blame] | 1996 |           return true; | 
| Ted Kremenek | 4d8ae4d | 2010-10-21 04:00:58 +0000 | [diff] [blame] | 1997 |       } | 
| Michael J. Spencer | 96827eb | 2010-07-27 04:46:02 +0000 | [diff] [blame] | 1998 |  | 
 | 1999 |     // We may be able to offer a FixItHint if it is a supported type. | 
 | 2000 |     PrintfSpecifier fixedFS = FS; | 
| Hans Wennborg | a7da215 | 2011-10-18 08:10:06 +0000 | [diff] [blame] | 2001 |     bool success = fixedFS.fixType(Ex->getType(), S.getLangOptions()); | 
| Michael J. Spencer | 96827eb | 2010-07-27 04:46:02 +0000 | [diff] [blame] | 2002 |  | 
 | 2003 |     if (success) { | 
 | 2004 |       // Get the fix string from the fixed format specifier | 
 | 2005 |       llvm::SmallString<128> buf; | 
 | 2006 |       llvm::raw_svector_ostream os(buf); | 
 | 2007 |       fixedFS.toString(os); | 
 | 2008 |  | 
| Ted Kremenek | 9325eaf | 2010-08-24 22:24:51 +0000 | [diff] [blame] | 2009 |       // FIXME: getRepresentativeType() perhaps should return a string | 
 | 2010 |       // instead of a QualType to better handle when the representative | 
 | 2011 |       // type is 'wint_t' (which is defined in the system headers). | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2012 |       EmitFormatDiagnostic( | 
 | 2013 |         S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) | 
 | 2014 |           << ATR.getRepresentativeType(S.Context) << Ex->getType() | 
 | 2015 |           << Ex->getSourceRange(), | 
 | 2016 |         getLocationOfByte(CS.getStart()), | 
 | 2017 |         /*IsStringLocation*/true, | 
 | 2018 |         getSpecifierRange(startSpecifier, specifierLen), | 
 | 2019 |         FixItHint::CreateReplacement( | 
 | 2020 |           getSpecifierRange(startSpecifier, specifierLen), | 
 | 2021 |           os.str())); | 
| Michael J. Spencer | 96827eb | 2010-07-27 04:46:02 +0000 | [diff] [blame] | 2022 |     } | 
 | 2023 |     else { | 
 | 2024 |       S.Diag(getLocationOfByte(CS.getStart()), | 
 | 2025 |              diag::warn_printf_conversion_argument_type_mismatch) | 
 | 2026 |         << ATR.getRepresentativeType(S.Context) << Ex->getType() | 
 | 2027 |         << getSpecifierRange(startSpecifier, specifierLen) | 
 | 2028 |         << Ex->getSourceRange(); | 
 | 2029 |     } | 
 | 2030 |   } | 
 | 2031 |  | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 2032 |   return true; | 
 | 2033 | } | 
 | 2034 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2035 | //===--- CHECK: Scanf format string checking ------------------------------===// | 
 | 2036 |  | 
 | 2037 | namespace {   | 
 | 2038 | class CheckScanfHandler : public CheckFormatHandler { | 
 | 2039 | public: | 
 | 2040 |   CheckScanfHandler(Sema &s, const StringLiteral *fexpr, | 
 | 2041 |                     const Expr *origFormatExpr, unsigned firstDataArg, | 
 | 2042 |                     unsigned numDataArgs, bool isObjCLiteral, | 
 | 2043 |                     const char *beg, bool hasVAListArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2044 |                     const CallExpr *theCall, unsigned formatIdx, | 
 | 2045 |                     bool inFunctionCall) | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2046 |   : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, | 
 | 2047 |                        numDataArgs, isObjCLiteral, beg, hasVAListArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2048 |                        theCall, formatIdx, inFunctionCall) {} | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2049 |    | 
 | 2050 |   bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, | 
 | 2051 |                             const char *startSpecifier, | 
 | 2052 |                             unsigned specifierLen); | 
| Ted Kremenek | c09b6a5 | 2010-07-19 21:25:57 +0000 | [diff] [blame] | 2053 |    | 
 | 2054 |   bool HandleInvalidScanfConversionSpecifier( | 
 | 2055 |           const analyze_scanf::ScanfSpecifier &FS, | 
 | 2056 |           const char *startSpecifier, | 
 | 2057 |           unsigned specifierLen); | 
| Ted Kremenek | b7c2101 | 2010-07-16 18:28:03 +0000 | [diff] [blame] | 2058 |  | 
 | 2059 |   void HandleIncompleteScanList(const char *start, const char *end); | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2060 | }; | 
| Ted Kremenek | 07d161f | 2010-01-29 01:50:07 +0000 | [diff] [blame] | 2061 | } | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 2062 |  | 
| Ted Kremenek | b7c2101 | 2010-07-16 18:28:03 +0000 | [diff] [blame] | 2063 | void CheckScanfHandler::HandleIncompleteScanList(const char *start, | 
 | 2064 |                                                  const char *end) { | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2065 |   EmitFormatDiagnostic(S.PDiag(diag::warn_scanf_scanlist_incomplete), | 
 | 2066 |                        getLocationOfByte(end), /*IsStringLocation*/true, | 
 | 2067 |                        getSpecifierRange(start, end - start)); | 
| Ted Kremenek | b7c2101 | 2010-07-16 18:28:03 +0000 | [diff] [blame] | 2068 | } | 
 | 2069 |  | 
| Ted Kremenek | c09b6a5 | 2010-07-19 21:25:57 +0000 | [diff] [blame] | 2070 | bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier( | 
 | 2071 |                                         const analyze_scanf::ScanfSpecifier &FS, | 
 | 2072 |                                         const char *startSpecifier, | 
 | 2073 |                                         unsigned specifierLen) { | 
 | 2074 |  | 
| Ted Kremenek | 6ecb950 | 2010-07-20 20:04:27 +0000 | [diff] [blame] | 2075 |   const analyze_scanf::ScanfConversionSpecifier &CS = | 
| Ted Kremenek | c09b6a5 | 2010-07-19 21:25:57 +0000 | [diff] [blame] | 2076 |     FS.getConversionSpecifier(); | 
 | 2077 |  | 
 | 2078 |   return HandleInvalidConversionSpecifier(FS.getArgIndex(), | 
 | 2079 |                                           getLocationOfByte(CS.getStart()), | 
 | 2080 |                                           startSpecifier, specifierLen, | 
 | 2081 |                                           CS.getStart(), CS.getLength()); | 
 | 2082 | } | 
 | 2083 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2084 | bool CheckScanfHandler::HandleScanfSpecifier( | 
 | 2085 |                                        const analyze_scanf::ScanfSpecifier &FS, | 
 | 2086 |                                        const char *startSpecifier, | 
 | 2087 |                                        unsigned specifierLen) { | 
 | 2088 |    | 
 | 2089 |   using namespace analyze_scanf; | 
 | 2090 |   using namespace analyze_format_string;   | 
 | 2091 |  | 
| Ted Kremenek | 6ecb950 | 2010-07-20 20:04:27 +0000 | [diff] [blame] | 2092 |   const ScanfConversionSpecifier &CS = FS.getConversionSpecifier(); | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2093 |  | 
| Ted Kremenek | baa4006 | 2010-07-19 22:01:06 +0000 | [diff] [blame] | 2094 |   // Handle case where '%' and '*' don't consume an argument.  These shouldn't | 
 | 2095 |   // be used to decide if we are using positional arguments consistently. | 
 | 2096 |   if (FS.consumesDataArgument()) { | 
 | 2097 |     if (atFirstArg) { | 
 | 2098 |       atFirstArg = false; | 
 | 2099 |       usesPositionalArgs = FS.usesPositionalArg(); | 
 | 2100 |     } | 
 | 2101 |     else if (usesPositionalArgs != FS.usesPositionalArg()) { | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2102 |       HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()), | 
 | 2103 |                                         startSpecifier, specifierLen); | 
| Ted Kremenek | baa4006 | 2010-07-19 22:01:06 +0000 | [diff] [blame] | 2104 |       return false; | 
 | 2105 |     } | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2106 |   } | 
 | 2107 |    | 
 | 2108 |   // Check if the field with is non-zero. | 
 | 2109 |   const OptionalAmount &Amt = FS.getFieldWidth(); | 
 | 2110 |   if (Amt.getHowSpecified() == OptionalAmount::Constant) { | 
 | 2111 |     if (Amt.getConstantAmount() == 0) { | 
 | 2112 |       const CharSourceRange &R = getSpecifierRange(Amt.getStart(), | 
 | 2113 |                                                    Amt.getConstantLength()); | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2114 |       EmitFormatDiagnostic(S.PDiag(diag::warn_scanf_nonzero_width), | 
 | 2115 |                            getLocationOfByte(Amt.getStart()), | 
 | 2116 |                            /*IsStringLocation*/true, R, | 
 | 2117 |                            FixItHint::CreateRemoval(R)); | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2118 |     } | 
 | 2119 |   } | 
 | 2120 |    | 
 | 2121 |   if (!FS.consumesDataArgument()) { | 
 | 2122 |     // FIXME: Technically specifying a precision or field width here | 
 | 2123 |     // makes no sense.  Worth issuing a warning at some point. | 
 | 2124 |     return true; | 
 | 2125 |   } | 
 | 2126 |    | 
 | 2127 |   // Consume the argument. | 
 | 2128 |   unsigned argIndex = FS.getArgIndex(); | 
 | 2129 |   if (argIndex < NumDataArgs) { | 
 | 2130 |       // The check to see if the argIndex is valid will come later. | 
 | 2131 |       // We set the bit here because we may exit early from this | 
 | 2132 |       // function if we encounter some other error. | 
 | 2133 |     CoveredArgs.set(argIndex); | 
 | 2134 |   } | 
 | 2135 |    | 
| Ted Kremenek | 1e51c20 | 2010-07-20 20:04:47 +0000 | [diff] [blame] | 2136 |   // Check the length modifier is valid with the given conversion specifier. | 
 | 2137 |   const LengthModifier &LM = FS.getLengthModifier(); | 
 | 2138 |   if (!FS.hasValidLengthModifier()) { | 
 | 2139 |     S.Diag(getLocationOfByte(LM.getStart()), | 
 | 2140 |            diag::warn_format_nonsensical_length) | 
 | 2141 |       << LM.toString() << CS.toString() | 
 | 2142 |       << getSpecifierRange(startSpecifier, specifierLen) | 
 | 2143 |       << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(), | 
 | 2144 |                                                     LM.getLength())); | 
 | 2145 |   } | 
 | 2146 |  | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2147 |   // The remaining checks depend on the data arguments. | 
 | 2148 |   if (HasVAListArg) | 
 | 2149 |     return true; | 
 | 2150 |    | 
| Ted Kremenek | 666a197 | 2010-07-26 19:45:42 +0000 | [diff] [blame] | 2151 |   if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2152 |     return false; | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2153 |    | 
 | 2154 |   // FIXME: Check that the argument type matches the format specifier. | 
 | 2155 |    | 
 | 2156 |   return true; | 
 | 2157 | } | 
 | 2158 |  | 
 | 2159 | void Sema::CheckFormatString(const StringLiteral *FExpr, | 
| Ted Kremenek | 0e5675d | 2010-02-10 02:16:30 +0000 | [diff] [blame] | 2160 |                              const Expr *OrigFormatExpr, | 
 | 2161 |                              const CallExpr *TheCall, bool HasVAListArg, | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2162 |                              unsigned format_idx, unsigned firstDataArg, | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2163 |                              bool isPrintf, bool inFunctionCall) { | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2164 |    | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 2165 |   // CHECK: is the format string a wide literal? | 
| Douglas Gregor | 5cee119 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 2166 |   if (!FExpr->isAscii()) { | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2167 |     CheckFormatHandler::EmitFormatDiagnostic( | 
 | 2168 |       *this, inFunctionCall, TheCall->getArg(format_idx), | 
 | 2169 |       PDiag(diag::warn_format_string_is_wide_literal), FExpr->getLocStart(), | 
 | 2170 |       /*IsStringLocation*/true, OrigFormatExpr->getSourceRange()); | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 2171 |     return; | 
 | 2172 |   } | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2173 |    | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 2174 |   // Str - The format string.  NOTE: this is NOT null-terminated! | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 2175 |   StringRef StrRef = FExpr->getString(); | 
| Benjamin Kramer | 2f4eaef | 2010-08-17 12:54:38 +0000 | [diff] [blame] | 2176 |   const char *Str = StrRef.data(); | 
 | 2177 |   unsigned StrLen = StrRef.size(); | 
| Ted Kremenek | 4cd5791 | 2011-09-29 05:52:16 +0000 | [diff] [blame] | 2178 |   const unsigned numDataArgs = TheCall->getNumArgs() - firstDataArg; | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2179 |    | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 2180 |   // CHECK: empty format string? | 
| Ted Kremenek | 4cd5791 | 2011-09-29 05:52:16 +0000 | [diff] [blame] | 2181 |   if (StrLen == 0 && numDataArgs > 0) { | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2182 |     CheckFormatHandler::EmitFormatDiagnostic( | 
 | 2183 |       *this, inFunctionCall, TheCall->getArg(format_idx), | 
 | 2184 |       PDiag(diag::warn_empty_format_string), FExpr->getLocStart(), | 
 | 2185 |       /*IsStringLocation*/true, OrigFormatExpr->getSourceRange()); | 
| Ted Kremenek | e0e5313 | 2010-01-28 23:39:18 +0000 | [diff] [blame] | 2186 |     return; | 
 | 2187 |   } | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2188 |    | 
 | 2189 |   if (isPrintf) { | 
 | 2190 |     CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, | 
| Ted Kremenek | 4cd5791 | 2011-09-29 05:52:16 +0000 | [diff] [blame] | 2191 |                          numDataArgs, isa<ObjCStringLiteral>(OrigFormatExpr), | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2192 |                          Str, HasVAListArg, TheCall, format_idx, | 
 | 2193 |                          inFunctionCall); | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2194 |    | 
 | 2195 |     if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen)) | 
 | 2196 |       H.DoneProcessing(); | 
 | 2197 |   } | 
 | 2198 |   else { | 
 | 2199 |     CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, | 
| Ted Kremenek | 4cd5791 | 2011-09-29 05:52:16 +0000 | [diff] [blame] | 2200 |                         numDataArgs, isa<ObjCStringLiteral>(OrigFormatExpr), | 
| Richard Trieu | 55733de | 2011-10-28 00:41:25 +0000 | [diff] [blame] | 2201 |                         Str, HasVAListArg, TheCall, format_idx, | 
 | 2202 |                         inFunctionCall); | 
| Ted Kremenek | 826a345 | 2010-07-16 02:11:22 +0000 | [diff] [blame] | 2203 |      | 
 | 2204 |     if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen)) | 
 | 2205 |       H.DoneProcessing(); | 
 | 2206 |   } | 
| Ted Kremenek | ce7024e | 2010-01-28 01:18:22 +0000 | [diff] [blame] | 2207 | } | 
 | 2208 |  | 
| Chandler Carruth | 7ccc95b | 2011-04-27 07:05:31 +0000 | [diff] [blame] | 2209 | //===--- CHECK: Standard memory functions ---------------------------------===// | 
 | 2210 |  | 
| Douglas Gregor | 2a053a3 | 2011-05-03 20:05:22 +0000 | [diff] [blame] | 2211 | /// \brief Determine whether the given type is a dynamic class type (e.g., | 
 | 2212 | /// whether it has a vtable). | 
 | 2213 | static bool isDynamicClassType(QualType T) { | 
 | 2214 |   if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) | 
 | 2215 |     if (CXXRecordDecl *Definition = Record->getDefinition()) | 
 | 2216 |       if (Definition->isDynamicClass()) | 
 | 2217 |         return true; | 
 | 2218 |    | 
 | 2219 |   return false; | 
 | 2220 | } | 
 | 2221 |  | 
| Chandler Carruth | a72a12f | 2011-06-21 23:04:20 +0000 | [diff] [blame] | 2222 | /// \brief If E is a sizeof expression, returns its argument expression, | 
| Chandler Carruth | 000d428 | 2011-06-16 09:09:40 +0000 | [diff] [blame] | 2223 | /// otherwise returns NULL. | 
 | 2224 | static const Expr *getSizeOfExprArg(const Expr* E) { | 
| Nico Weber | e4a1c64 | 2011-06-14 16:14:58 +0000 | [diff] [blame] | 2225 |   if (const UnaryExprOrTypeTraitExpr *SizeOf = | 
| Chandler Carruth | 000d428 | 2011-06-16 09:09:40 +0000 | [diff] [blame] | 2226 |       dyn_cast<UnaryExprOrTypeTraitExpr>(E)) | 
 | 2227 |     if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType()) | 
 | 2228 |       return SizeOf->getArgumentExpr()->IgnoreParenImpCasts(); | 
| Nico Weber | e4a1c64 | 2011-06-14 16:14:58 +0000 | [diff] [blame] | 2229 |  | 
| Chandler Carruth | 000d428 | 2011-06-16 09:09:40 +0000 | [diff] [blame] | 2230 |   return 0; | 
 | 2231 | } | 
 | 2232 |  | 
| Chandler Carruth | a72a12f | 2011-06-21 23:04:20 +0000 | [diff] [blame] | 2233 | /// \brief If E is a sizeof expression, returns its argument type. | 
| Chandler Carruth | 000d428 | 2011-06-16 09:09:40 +0000 | [diff] [blame] | 2234 | static QualType getSizeOfArgType(const Expr* E) { | 
 | 2235 |   if (const UnaryExprOrTypeTraitExpr *SizeOf = | 
 | 2236 |       dyn_cast<UnaryExprOrTypeTraitExpr>(E)) | 
 | 2237 |     if (SizeOf->getKind() == clang::UETT_SizeOf) | 
 | 2238 |       return SizeOf->getTypeOfArgument(); | 
 | 2239 |  | 
 | 2240 |   return QualType(); | 
| Nico Weber | e4a1c64 | 2011-06-14 16:14:58 +0000 | [diff] [blame] | 2241 | } | 
 | 2242 |  | 
| Chandler Carruth | 7ccc95b | 2011-04-27 07:05:31 +0000 | [diff] [blame] | 2243 | /// \brief Check for dangerous or invalid arguments to memset(). | 
 | 2244 | /// | 
| Chandler Carruth | 929f013 | 2011-06-03 06:23:57 +0000 | [diff] [blame] | 2245 | /// This issues warnings on known problematic, dangerous or unspecified | 
| Matt Beaumont-Gay | cc2f30c | 2011-08-05 00:22:34 +0000 | [diff] [blame] | 2246 | /// arguments to the standard 'memset', 'memcpy', 'memmove', and 'memcmp' | 
 | 2247 | /// function calls. | 
| Chandler Carruth | 7ccc95b | 2011-04-27 07:05:31 +0000 | [diff] [blame] | 2248 | /// | 
 | 2249 | /// \param Call The call expression to diagnose. | 
| Matt Beaumont-Gay | cc2f30c | 2011-08-05 00:22:34 +0000 | [diff] [blame] | 2250 | void Sema::CheckMemaccessArguments(const CallExpr *Call, | 
 | 2251 |                                    CheckedMemoryFunction CMF, | 
 | 2252 |                                    IdentifierInfo *FnName) { | 
| Ted Kremenek | 1d59f7f | 2011-04-28 01:38:02 +0000 | [diff] [blame] | 2253 |   // It is possible to have a non-standard definition of memset.  Validate | 
| Douglas Gregor | 707a23e | 2011-06-16 17:56:04 +0000 | [diff] [blame] | 2254 |   // we have enough arguments, and if not, abort further checking. | 
| Nico Weber | cda5782 | 2011-10-13 22:30:23 +0000 | [diff] [blame] | 2255 |   unsigned ExpectedNumArgs = (CMF == CMF_Strndup ? 2 : 3); | 
 | 2256 |   if (Call->getNumArgs() < ExpectedNumArgs) | 
| Ted Kremenek | 1d59f7f | 2011-04-28 01:38:02 +0000 | [diff] [blame] | 2257 |     return; | 
 | 2258 |  | 
| Nico Weber | cda5782 | 2011-10-13 22:30:23 +0000 | [diff] [blame] | 2259 |   unsigned LastArg = (CMF == CMF_Memset || CMF == CMF_Strndup ? 1 : 2); | 
 | 2260 |   unsigned LenArg = (CMF == CMF_Strndup ? 1 : 2); | 
 | 2261 |   const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts(); | 
| Chandler Carruth | 000d428 | 2011-06-16 09:09:40 +0000 | [diff] [blame] | 2262 |  | 
 | 2263 |   // We have special checking when the length is a sizeof expression. | 
 | 2264 |   QualType SizeOfArgTy = getSizeOfArgType(LenExpr); | 
 | 2265 |   const Expr *SizeOfArg = getSizeOfExprArg(LenExpr); | 
 | 2266 |   llvm::FoldingSetNodeID SizeOfArgID; | 
 | 2267 |  | 
| Douglas Gregor | 06bc9eb | 2011-05-03 20:37:33 +0000 | [diff] [blame] | 2268 |   for (unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) { | 
 | 2269 |     const Expr *Dest = Call->getArg(ArgIdx)->IgnoreParenImpCasts(); | 
| Nico Weber | e4a1c64 | 2011-06-14 16:14:58 +0000 | [diff] [blame] | 2270 |     SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange(); | 
| Chandler Carruth | 7ccc95b | 2011-04-27 07:05:31 +0000 | [diff] [blame] | 2271 |  | 
| Douglas Gregor | 06bc9eb | 2011-05-03 20:37:33 +0000 | [diff] [blame] | 2272 |     QualType DestTy = Dest->getType(); | 
 | 2273 |     if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) { | 
 | 2274 |       QualType PointeeTy = DestPtrTy->getPointeeType(); | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 2275 |  | 
| Chandler Carruth | 000d428 | 2011-06-16 09:09:40 +0000 | [diff] [blame] | 2276 |       // Never warn about void type pointers. This can be used to suppress | 
 | 2277 |       // false positives. | 
 | 2278 |       if (PointeeTy->isVoidType()) | 
| Douglas Gregor | 06bc9eb | 2011-05-03 20:37:33 +0000 | [diff] [blame] | 2279 |         continue; | 
| Chandler Carruth | 7ccc95b | 2011-04-27 07:05:31 +0000 | [diff] [blame] | 2280 |  | 
| Chandler Carruth | 000d428 | 2011-06-16 09:09:40 +0000 | [diff] [blame] | 2281 |       // Catch "memset(p, 0, sizeof(p))" -- needs to be sizeof(*p). Do this by | 
 | 2282 |       // actually comparing the expressions for equality. Because computing the | 
 | 2283 |       // expression IDs can be expensive, we only do this if the diagnostic is | 
 | 2284 |       // enabled. | 
 | 2285 |       if (SizeOfArg && | 
 | 2286 |           Diags.getDiagnosticLevel(diag::warn_sizeof_pointer_expr_memaccess, | 
 | 2287 |                                    SizeOfArg->getExprLoc())) { | 
 | 2288 |         // We only compute IDs for expressions if the warning is enabled, and | 
 | 2289 |         // cache the sizeof arg's ID. | 
 | 2290 |         if (SizeOfArgID == llvm::FoldingSetNodeID()) | 
 | 2291 |           SizeOfArg->Profile(SizeOfArgID, Context, true); | 
 | 2292 |         llvm::FoldingSetNodeID DestID; | 
 | 2293 |         Dest->Profile(DestID, Context, true); | 
 | 2294 |         if (DestID == SizeOfArgID) { | 
| Nico Weber | cda5782 | 2011-10-13 22:30:23 +0000 | [diff] [blame] | 2295 |           // TODO: For strncpy() and friends, this could suggest sizeof(dst) | 
 | 2296 |           //       over sizeof(src) as well. | 
| Chandler Carruth | 000d428 | 2011-06-16 09:09:40 +0000 | [diff] [blame] | 2297 |           unsigned ActionIdx = 0; // Default is to suggest dereferencing. | 
 | 2298 |           if (const UnaryOperator *UnaryOp = dyn_cast<UnaryOperator>(Dest)) | 
 | 2299 |             if (UnaryOp->getOpcode() == UO_AddrOf) | 
 | 2300 |               ActionIdx = 1; // If its an address-of operator, just remove it. | 
 | 2301 |           if (Context.getTypeSize(PointeeTy) == Context.getCharWidth()) | 
 | 2302 |             ActionIdx = 2; // If the pointee's size is sizeof(char), | 
 | 2303 |                            // suggest an explicit length. | 
| Nico Weber | cda5782 | 2011-10-13 22:30:23 +0000 | [diff] [blame] | 2304 |           unsigned DestSrcSelect = (CMF == CMF_Strndup ? 1 : ArgIdx); | 
| Chandler Carruth | 000d428 | 2011-06-16 09:09:40 +0000 | [diff] [blame] | 2305 |           DiagRuntimeBehavior(SizeOfArg->getExprLoc(), Dest, | 
 | 2306 |                               PDiag(diag::warn_sizeof_pointer_expr_memaccess) | 
| Nico Weber | cda5782 | 2011-10-13 22:30:23 +0000 | [diff] [blame] | 2307 |                                 << FnName << DestSrcSelect << ActionIdx | 
| Chandler Carruth | 000d428 | 2011-06-16 09:09:40 +0000 | [diff] [blame] | 2308 |                                 << Dest->getSourceRange() | 
 | 2309 |                                 << SizeOfArg->getSourceRange()); | 
 | 2310 |           break; | 
 | 2311 |         } | 
 | 2312 |       } | 
 | 2313 |  | 
 | 2314 |       // Also check for cases where the sizeof argument is the exact same | 
 | 2315 |       // type as the memory argument, and where it points to a user-defined | 
 | 2316 |       // record type. | 
 | 2317 |       if (SizeOfArgTy != QualType()) { | 
 | 2318 |         if (PointeeTy->isRecordType() && | 
 | 2319 |             Context.typesAreCompatible(SizeOfArgTy, DestTy)) { | 
 | 2320 |           DiagRuntimeBehavior(LenExpr->getExprLoc(), Dest, | 
 | 2321 |                               PDiag(diag::warn_sizeof_pointer_type_memaccess) | 
 | 2322 |                                 << FnName << SizeOfArgTy << ArgIdx | 
 | 2323 |                                 << PointeeTy << Dest->getSourceRange() | 
 | 2324 |                                 << LenExpr->getSourceRange()); | 
 | 2325 |           break; | 
 | 2326 |         } | 
| Nico Weber | e4a1c64 | 2011-06-14 16:14:58 +0000 | [diff] [blame] | 2327 |       } | 
 | 2328 |  | 
| Douglas Gregor | 06bc9eb | 2011-05-03 20:37:33 +0000 | [diff] [blame] | 2329 |       // Always complain about dynamic classes. | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 2330 |       if (isDynamicClassType(PointeeTy)) | 
| Matt Beaumont-Gay | 5c5218e | 2011-08-19 20:40:18 +0000 | [diff] [blame] | 2331 |         DiagRuntimeBehavior( | 
 | 2332 |           Dest->getExprLoc(), Dest, | 
 | 2333 |           PDiag(diag::warn_dyn_class_memaccess) | 
 | 2334 |             << (CMF == CMF_Memcmp ? ArgIdx + 2 : ArgIdx) << FnName << PointeeTy | 
 | 2335 |             // "overwritten" if we're warning about the destination for any call | 
 | 2336 |             // but memcmp; otherwise a verb appropriate to the call. | 
 | 2337 |             << (ArgIdx == 0 && CMF != CMF_Memcmp ? 0 : (unsigned)CMF) | 
 | 2338 |             << Call->getCallee()->getSourceRange()); | 
| Douglas Gregor | 707a23e | 2011-06-16 17:56:04 +0000 | [diff] [blame] | 2339 |       else if (PointeeTy.hasNonTrivialObjCLifetime() && CMF != CMF_Memset) | 
| Matt Beaumont-Gay | 5c5218e | 2011-08-19 20:40:18 +0000 | [diff] [blame] | 2340 |         DiagRuntimeBehavior( | 
 | 2341 |           Dest->getExprLoc(), Dest, | 
 | 2342 |           PDiag(diag::warn_arc_object_memaccess) | 
 | 2343 |             << ArgIdx << FnName << PointeeTy | 
 | 2344 |             << Call->getCallee()->getSourceRange()); | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 2345 |       else | 
| Douglas Gregor | 06bc9eb | 2011-05-03 20:37:33 +0000 | [diff] [blame] | 2346 |         continue; | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 2347 |  | 
 | 2348 |       DiagRuntimeBehavior( | 
 | 2349 |         Dest->getExprLoc(), Dest, | 
| Chandler Carruth | 929f013 | 2011-06-03 06:23:57 +0000 | [diff] [blame] | 2350 |         PDiag(diag::note_bad_memaccess_silence) | 
| Douglas Gregor | 06bc9eb | 2011-05-03 20:37:33 +0000 | [diff] [blame] | 2351 |           << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); | 
 | 2352 |       break; | 
 | 2353 |     } | 
| Chandler Carruth | 7ccc95b | 2011-04-27 07:05:31 +0000 | [diff] [blame] | 2354 |   } | 
 | 2355 | } | 
 | 2356 |  | 
| Ted Kremenek | bd5da9d | 2011-08-18 20:55:45 +0000 | [diff] [blame] | 2357 | // A little helper routine: ignore addition and subtraction of integer literals. | 
 | 2358 | // This intentionally does not ignore all integer constant expressions because | 
 | 2359 | // we don't want to remove sizeof(). | 
 | 2360 | static const Expr *ignoreLiteralAdditions(const Expr *Ex, ASTContext &Ctx) { | 
 | 2361 |   Ex = Ex->IgnoreParenCasts(); | 
 | 2362 |  | 
 | 2363 |   for (;;) { | 
 | 2364 |     const BinaryOperator * BO = dyn_cast<BinaryOperator>(Ex); | 
 | 2365 |     if (!BO || !BO->isAdditiveOp()) | 
 | 2366 |       break; | 
 | 2367 |  | 
 | 2368 |     const Expr *RHS = BO->getRHS()->IgnoreParenCasts(); | 
 | 2369 |     const Expr *LHS = BO->getLHS()->IgnoreParenCasts(); | 
 | 2370 |      | 
 | 2371 |     if (isa<IntegerLiteral>(RHS)) | 
 | 2372 |       Ex = LHS; | 
 | 2373 |     else if (isa<IntegerLiteral>(LHS)) | 
 | 2374 |       Ex = RHS; | 
 | 2375 |     else | 
 | 2376 |       break; | 
 | 2377 |   } | 
 | 2378 |  | 
 | 2379 |   return Ex; | 
 | 2380 | } | 
 | 2381 |  | 
 | 2382 | // Warn if the user has made the 'size' argument to strlcpy or strlcat | 
 | 2383 | // be the size of the source, instead of the destination. | 
 | 2384 | void Sema::CheckStrlcpycatArguments(const CallExpr *Call, | 
 | 2385 |                                     IdentifierInfo *FnName) { | 
 | 2386 |  | 
 | 2387 |   // Don't crash if the user has the wrong number of arguments | 
 | 2388 |   if (Call->getNumArgs() != 3) | 
 | 2389 |     return; | 
 | 2390 |  | 
 | 2391 |   const Expr *SrcArg = ignoreLiteralAdditions(Call->getArg(1), Context); | 
 | 2392 |   const Expr *SizeArg = ignoreLiteralAdditions(Call->getArg(2), Context); | 
 | 2393 |   const Expr *CompareWithSrc = NULL; | 
 | 2394 |    | 
 | 2395 |   // Look for 'strlcpy(dst, x, sizeof(x))' | 
 | 2396 |   if (const Expr *Ex = getSizeOfExprArg(SizeArg)) | 
 | 2397 |     CompareWithSrc = Ex; | 
 | 2398 |   else { | 
 | 2399 |     // Look for 'strlcpy(dst, x, strlen(x))' | 
 | 2400 |     if (const CallExpr *SizeCall = dyn_cast<CallExpr>(SizeArg)) { | 
 | 2401 |       if (SizeCall->isBuiltinCall(Context) == Builtin::BIstrlen | 
 | 2402 |           && SizeCall->getNumArgs() == 1) | 
 | 2403 |         CompareWithSrc = ignoreLiteralAdditions(SizeCall->getArg(0), Context); | 
 | 2404 |     } | 
 | 2405 |   } | 
 | 2406 |  | 
 | 2407 |   if (!CompareWithSrc) | 
 | 2408 |     return; | 
 | 2409 |  | 
 | 2410 |   // Determine if the argument to sizeof/strlen is equal to the source | 
 | 2411 |   // argument.  In principle there's all kinds of things you could do | 
 | 2412 |   // here, for instance creating an == expression and evaluating it with | 
 | 2413 |   // EvaluateAsBooleanCondition, but this uses a more direct technique: | 
 | 2414 |   const DeclRefExpr *SrcArgDRE = dyn_cast<DeclRefExpr>(SrcArg); | 
 | 2415 |   if (!SrcArgDRE) | 
 | 2416 |     return; | 
 | 2417 |    | 
 | 2418 |   const DeclRefExpr *CompareWithSrcDRE = dyn_cast<DeclRefExpr>(CompareWithSrc); | 
 | 2419 |   if (!CompareWithSrcDRE ||  | 
 | 2420 |       SrcArgDRE->getDecl() != CompareWithSrcDRE->getDecl()) | 
 | 2421 |     return; | 
 | 2422 |    | 
 | 2423 |   const Expr *OriginalSizeArg = Call->getArg(2); | 
 | 2424 |   Diag(CompareWithSrcDRE->getLocStart(), diag::warn_strlcpycat_wrong_size) | 
 | 2425 |     << OriginalSizeArg->getSourceRange() << FnName; | 
 | 2426 |    | 
 | 2427 |   // Output a FIXIT hint if the destination is an array (rather than a | 
 | 2428 |   // pointer to an array).  This could be enhanced to handle some | 
 | 2429 |   // pointers if we know the actual size, like if DstArg is 'array+2' | 
 | 2430 |   // we could say 'sizeof(array)-2'. | 
 | 2431 |   const Expr *DstArg = Call->getArg(0)->IgnoreParenImpCasts(); | 
| Ted Kremenek | 8f74622 | 2011-08-18 22:48:41 +0000 | [diff] [blame] | 2432 |   QualType DstArgTy = DstArg->getType(); | 
| Ted Kremenek | bd5da9d | 2011-08-18 20:55:45 +0000 | [diff] [blame] | 2433 |    | 
| Ted Kremenek | 8f74622 | 2011-08-18 22:48:41 +0000 | [diff] [blame] | 2434 |   // Only handle constant-sized or VLAs, but not flexible members. | 
 | 2435 |   if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(DstArgTy)) { | 
 | 2436 |     // Only issue the FIXIT for arrays of size > 1. | 
 | 2437 |     if (CAT->getSize().getSExtValue() <= 1) | 
 | 2438 |       return; | 
 | 2439 |   } else if (!DstArgTy->isVariableArrayType()) { | 
 | 2440 |     return; | 
| Ted Kremenek | bd5da9d | 2011-08-18 20:55:45 +0000 | [diff] [blame] | 2441 |   } | 
| Ted Kremenek | 8f74622 | 2011-08-18 22:48:41 +0000 | [diff] [blame] | 2442 |  | 
 | 2443 |   llvm::SmallString<128> sizeString; | 
 | 2444 |   llvm::raw_svector_ostream OS(sizeString); | 
 | 2445 |   OS << "sizeof("; | 
| Douglas Gregor | 8987b23 | 2011-09-27 23:30:47 +0000 | [diff] [blame] | 2446 |   DstArg->printPretty(OS, Context, 0, getPrintingPolicy()); | 
| Ted Kremenek | 8f74622 | 2011-08-18 22:48:41 +0000 | [diff] [blame] | 2447 |   OS << ")"; | 
 | 2448 |    | 
 | 2449 |   Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size) | 
 | 2450 |     << FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(), | 
 | 2451 |                                     OS.str()); | 
| Ted Kremenek | bd5da9d | 2011-08-18 20:55:45 +0000 | [diff] [blame] | 2452 | } | 
 | 2453 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2454 | //===--- CHECK: Return Address of Stack Variable --------------------------===// | 
 | 2455 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 2456 | static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars); | 
 | 2457 | static Expr *EvalAddr(Expr* E, SmallVectorImpl<DeclRefExpr *> &refVars); | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2458 |  | 
 | 2459 | /// CheckReturnStackAddr - Check if a return statement returns the address | 
 | 2460 | ///   of a stack variable. | 
 | 2461 | void | 
 | 2462 | Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, | 
 | 2463 |                            SourceLocation ReturnLoc) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2464 |  | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2465 |   Expr *stackE = 0; | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 2466 |   SmallVector<DeclRefExpr *, 8> refVars; | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2467 |  | 
 | 2468 |   // Perform checking for returned stack addresses, local blocks, | 
 | 2469 |   // label addresses or references to temporaries. | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 2470 |   if (lhsType->isPointerType() || | 
 | 2471 |       (!getLangOptions().ObjCAutoRefCount && lhsType->isBlockPointerType())) { | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2472 |     stackE = EvalAddr(RetValExp, refVars); | 
| Mike Stump | ac5fc7c | 2009-08-04 21:02:39 +0000 | [diff] [blame] | 2473 |   } else if (lhsType->isReferenceType()) { | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2474 |     stackE = EvalVal(RetValExp, refVars); | 
 | 2475 |   } | 
 | 2476 |  | 
 | 2477 |   if (stackE == 0) | 
 | 2478 |     return; // Nothing suspicious was found. | 
 | 2479 |  | 
 | 2480 |   SourceLocation diagLoc; | 
 | 2481 |   SourceRange diagRange; | 
 | 2482 |   if (refVars.empty()) { | 
 | 2483 |     diagLoc = stackE->getLocStart(); | 
 | 2484 |     diagRange = stackE->getSourceRange(); | 
 | 2485 |   } else { | 
 | 2486 |     // We followed through a reference variable. 'stackE' contains the | 
 | 2487 |     // problematic expression but we will warn at the return statement pointing | 
 | 2488 |     // at the reference variable. We will later display the "trail" of | 
 | 2489 |     // reference variables using notes. | 
 | 2490 |     diagLoc = refVars[0]->getLocStart(); | 
 | 2491 |     diagRange = refVars[0]->getSourceRange(); | 
 | 2492 |   } | 
 | 2493 |  | 
 | 2494 |   if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var. | 
 | 2495 |     Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref | 
 | 2496 |                                              : diag::warn_ret_stack_addr) | 
 | 2497 |      << DR->getDecl()->getDeclName() << diagRange; | 
 | 2498 |   } else if (isa<BlockExpr>(stackE)) { // local block. | 
 | 2499 |     Diag(diagLoc, diag::err_ret_local_block) << diagRange; | 
 | 2500 |   } else if (isa<AddrLabelExpr>(stackE)) { // address of label. | 
 | 2501 |     Diag(diagLoc, diag::warn_ret_addr_label) << diagRange; | 
 | 2502 |   } else { // local temporary. | 
 | 2503 |     Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref | 
 | 2504 |                                              : diag::warn_ret_local_temp_addr) | 
 | 2505 |      << diagRange; | 
 | 2506 |   } | 
 | 2507 |  | 
 | 2508 |   // Display the "trail" of reference variables that we followed until we | 
 | 2509 |   // found the problematic expression using notes. | 
 | 2510 |   for (unsigned i = 0, e = refVars.size(); i != e; ++i) { | 
 | 2511 |     VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl()); | 
 | 2512 |     // If this var binds to another reference var, show the range of the next | 
 | 2513 |     // var, otherwise the var binds to the problematic expression, in which case | 
 | 2514 |     // show the range of the expression. | 
 | 2515 |     SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange() | 
 | 2516 |                                   : stackE->getSourceRange(); | 
 | 2517 |     Diag(VD->getLocation(), diag::note_ref_var_local_bind) | 
 | 2518 |       << VD->getDeclName() << range; | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2519 |   } | 
 | 2520 | } | 
 | 2521 |  | 
 | 2522 | /// EvalAddr - EvalAddr and EvalVal are mutually recursive functions that | 
 | 2523 | ///  check if the expression in a return statement evaluates to an address | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2524 | ///  to a location on the stack, a local block, an address of a label, or a | 
 | 2525 | ///  reference to local temporary. The recursion is used to traverse the | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2526 | ///  AST of the return expression, with recursion backtracking when we | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2527 | ///  encounter a subexpression that (1) clearly does not lead to one of the | 
 | 2528 | ///  above problematic expressions (2) is something we cannot determine leads to | 
 | 2529 | ///  a problematic expression based on such local checking. | 
 | 2530 | /// | 
 | 2531 | ///  Both EvalAddr and EvalVal follow through reference variables to evaluate | 
 | 2532 | ///  the expression that they point to. Such variables are added to the | 
 | 2533 | ///  'refVars' vector so that we know what the reference variable "trail" was. | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2534 | /// | 
| Ted Kremenek | e8c600f | 2007-08-28 17:02:55 +0000 | [diff] [blame] | 2535 | ///  EvalAddr processes expressions that are pointers that are used as | 
 | 2536 | ///  references (and not L-values).  EvalVal handles all other values. | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2537 | ///  At the base case of the recursion is a check for the above problematic | 
 | 2538 | ///  expressions. | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2539 | /// | 
 | 2540 | ///  This implementation handles: | 
 | 2541 | /// | 
 | 2542 | ///   * pointer-to-pointer casts | 
 | 2543 | ///   * implicit conversions from array references to pointers | 
 | 2544 | ///   * taking the address of fields | 
 | 2545 | ///   * arbitrary interplay between "&" and "*" operators | 
 | 2546 | ///   * pointer arithmetic from an address of a stack variable | 
 | 2547 | ///   * taking the address of an array element where the array is on the stack | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 2548 | static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) { | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2549 |   if (E->isTypeDependent()) | 
 | 2550 |       return NULL; | 
 | 2551 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2552 |   // We should only be called for evaluating pointer expressions. | 
| David Chisnall | 0f43656 | 2009-08-17 16:35:33 +0000 | [diff] [blame] | 2553 |   assert((E->getType()->isAnyPointerType() || | 
| Steve Naroff | dd972f2 | 2008-09-05 22:11:13 +0000 | [diff] [blame] | 2554 |           E->getType()->isBlockPointerType() || | 
| Ted Kremenek | a526c5c | 2008-01-07 19:49:32 +0000 | [diff] [blame] | 2555 |           E->getType()->isObjCQualifiedIdType()) && | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2556 |          "EvalAddr only works on pointers"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2557 |  | 
| Peter Collingbourne | f111d93 | 2011-04-15 00:35:48 +0000 | [diff] [blame] | 2558 |   E = E->IgnoreParens(); | 
 | 2559 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2560 |   // Our "symbolic interpreter" is just a dispatch off the currently | 
 | 2561 |   // viewed AST node.  We then recursively traverse the AST by calling | 
 | 2562 |   // EvalAddr and EvalVal appropriately. | 
 | 2563 |   switch (E->getStmtClass()) { | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2564 |   case Stmt::DeclRefExprClass: { | 
 | 2565 |     DeclRefExpr *DR = cast<DeclRefExpr>(E); | 
 | 2566 |  | 
 | 2567 |     if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) | 
 | 2568 |       // If this is a reference variable, follow through to the expression that | 
 | 2569 |       // it points to. | 
 | 2570 |       if (V->hasLocalStorage() && | 
 | 2571 |           V->getType()->isReferenceType() && V->hasInit()) { | 
 | 2572 |         // Add the reference variable to the "trail". | 
 | 2573 |         refVars.push_back(DR); | 
 | 2574 |         return EvalAddr(V->getInit(), refVars); | 
 | 2575 |       } | 
 | 2576 |  | 
 | 2577 |     return NULL; | 
 | 2578 |   } | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2579 |  | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2580 |   case Stmt::UnaryOperatorClass: { | 
 | 2581 |     // The only unary operator that make sense to handle here | 
 | 2582 |     // is AddrOf.  All others don't make sense as pointers. | 
 | 2583 |     UnaryOperator *U = cast<UnaryOperator>(E); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2584 |  | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 2585 |     if (U->getOpcode() == UO_AddrOf) | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2586 |       return EvalVal(U->getSubExpr(), refVars); | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2587 |     else | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2588 |       return NULL; | 
 | 2589 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2590 |  | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2591 |   case Stmt::BinaryOperatorClass: { | 
 | 2592 |     // Handle pointer arithmetic.  All other binary operators are not valid | 
 | 2593 |     // in this context. | 
 | 2594 |     BinaryOperator *B = cast<BinaryOperator>(E); | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 2595 |     BinaryOperatorKind op = B->getOpcode(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2596 |  | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 2597 |     if (op != BO_Add && op != BO_Sub) | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2598 |       return NULL; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2599 |  | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2600 |     Expr *Base = B->getLHS(); | 
 | 2601 |  | 
 | 2602 |     // Determine which argument is the real pointer base.  It could be | 
 | 2603 |     // the RHS argument instead of the LHS. | 
 | 2604 |     if (!Base->getType()->isPointerType()) Base = B->getRHS(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2605 |  | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2606 |     assert (Base->getType()->isPointerType()); | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2607 |     return EvalAddr(Base, refVars); | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2608 |   } | 
| Steve Naroff | 61f40a2 | 2008-09-10 19:17:48 +0000 | [diff] [blame] | 2609 |  | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2610 |   // For conditional operators we need to see if either the LHS or RHS are | 
 | 2611 |   // valid DeclRefExpr*s.  If one of them is valid, we return it. | 
 | 2612 |   case Stmt::ConditionalOperatorClass: { | 
 | 2613 |     ConditionalOperator *C = cast<ConditionalOperator>(E); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2614 |  | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2615 |     // Handle the GNU extension for missing LHS. | 
| Douglas Gregor | 9ee5ee8 | 2010-10-21 16:21:08 +0000 | [diff] [blame] | 2616 |     if (Expr *lhsExpr = C->getLHS()) { | 
 | 2617 |     // In C++, we can have a throw-expression, which has 'void' type. | 
 | 2618 |       if (!lhsExpr->getType()->isVoidType()) | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2619 |         if (Expr* LHS = EvalAddr(lhsExpr, refVars)) | 
| Douglas Gregor | 9ee5ee8 | 2010-10-21 16:21:08 +0000 | [diff] [blame] | 2620 |           return LHS; | 
 | 2621 |     } | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2622 |  | 
| Douglas Gregor | 9ee5ee8 | 2010-10-21 16:21:08 +0000 | [diff] [blame] | 2623 |     // In C++, we can have a throw-expression, which has 'void' type. | 
 | 2624 |     if (C->getRHS()->getType()->isVoidType()) | 
 | 2625 |       return NULL; | 
 | 2626 |  | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2627 |     return EvalAddr(C->getRHS(), refVars); | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2628 |   } | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2629 |    | 
 | 2630 |   case Stmt::BlockExprClass: | 
| John McCall | 469a1eb | 2011-02-02 13:00:07 +0000 | [diff] [blame] | 2631 |     if (cast<BlockExpr>(E)->getBlockDecl()->hasCaptures()) | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2632 |       return E; // local block. | 
 | 2633 |     return NULL; | 
 | 2634 |  | 
 | 2635 |   case Stmt::AddrLabelExprClass: | 
 | 2636 |     return E; // address of label. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2637 |  | 
| Ted Kremenek | 54b5274 | 2008-08-07 00:49:01 +0000 | [diff] [blame] | 2638 |   // For casts, we need to handle conversions from arrays to | 
 | 2639 |   // pointer values, and pointer-to-pointer conversions. | 
| Douglas Gregor | 49badde | 2008-10-27 19:41:14 +0000 | [diff] [blame] | 2640 |   case Stmt::ImplicitCastExprClass: | 
| Douglas Gregor | 6eec8e8 | 2008-10-28 15:36:24 +0000 | [diff] [blame] | 2641 |   case Stmt::CStyleCastExprClass: | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 2642 |   case Stmt::CXXFunctionalCastExprClass: | 
 | 2643 |   case Stmt::ObjCBridgedCastExprClass: { | 
| Argyrios Kyrtzidis | 0835a3c | 2008-08-18 23:01:59 +0000 | [diff] [blame] | 2644 |     Expr* SubExpr = cast<CastExpr>(E)->getSubExpr(); | 
| Ted Kremenek | 54b5274 | 2008-08-07 00:49:01 +0000 | [diff] [blame] | 2645 |     QualType T = SubExpr->getType(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2646 |  | 
| Steve Naroff | dd972f2 | 2008-09-05 22:11:13 +0000 | [diff] [blame] | 2647 |     if (SubExpr->getType()->isPointerType() || | 
 | 2648 |         SubExpr->getType()->isBlockPointerType() || | 
 | 2649 |         SubExpr->getType()->isObjCQualifiedIdType()) | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2650 |       return EvalAddr(SubExpr, refVars); | 
| Ted Kremenek | 54b5274 | 2008-08-07 00:49:01 +0000 | [diff] [blame] | 2651 |     else if (T->isArrayType()) | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2652 |       return EvalVal(SubExpr, refVars); | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2653 |     else | 
| Ted Kremenek | 54b5274 | 2008-08-07 00:49:01 +0000 | [diff] [blame] | 2654 |       return 0; | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2655 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2656 |  | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2657 |   // C++ casts.  For dynamic casts, static casts, and const casts, we | 
 | 2658 |   // are always converting from a pointer-to-pointer, so we just blow | 
| Douglas Gregor | 49badde | 2008-10-27 19:41:14 +0000 | [diff] [blame] | 2659 |   // through the cast.  In the case the dynamic cast doesn't fail (and | 
 | 2660 |   // return NULL), we take the conservative route and report cases | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2661 |   // where we return the address of a stack variable.  For Reinterpre | 
| Douglas Gregor | 49badde | 2008-10-27 19:41:14 +0000 | [diff] [blame] | 2662 |   // FIXME: The comment about is wrong; we're not always converting | 
 | 2663 |   // from pointer to pointer. I'm guessing that this code should also | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2664 |   // handle references to objects. | 
 | 2665 |   case Stmt::CXXStaticCastExprClass: | 
 | 2666 |   case Stmt::CXXDynamicCastExprClass: | 
| Douglas Gregor | 49badde | 2008-10-27 19:41:14 +0000 | [diff] [blame] | 2667 |   case Stmt::CXXConstCastExprClass: | 
 | 2668 |   case Stmt::CXXReinterpretCastExprClass: { | 
 | 2669 |       Expr *S = cast<CXXNamedCastExpr>(E)->getSubExpr(); | 
| Steve Naroff | dd972f2 | 2008-09-05 22:11:13 +0000 | [diff] [blame] | 2670 |       if (S->getType()->isPointerType() || S->getType()->isBlockPointerType()) | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2671 |         return EvalAddr(S, refVars); | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2672 |       else | 
 | 2673 |         return NULL; | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2674 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2675 |  | 
| Douglas Gregor | 03e8003 | 2011-06-21 17:03:29 +0000 | [diff] [blame] | 2676 |   case Stmt::MaterializeTemporaryExprClass: | 
 | 2677 |     if (Expr *Result = EvalAddr( | 
 | 2678 |                          cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(), | 
 | 2679 |                                 refVars)) | 
 | 2680 |       return Result; | 
 | 2681 |        | 
 | 2682 |     return E; | 
 | 2683 |        | 
| Chris Lattner | fae3f1f | 2007-12-28 05:31:15 +0000 | [diff] [blame] | 2684 |   // Everything else: we simply don't reason about them. | 
 | 2685 |   default: | 
 | 2686 |     return NULL; | 
 | 2687 |   } | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2688 | } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2689 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2690 |  | 
 | 2691 | ///  EvalVal - This function is complements EvalAddr in the mutual recursion. | 
 | 2692 | ///   See the comments for EvalAddr for more details. | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 2693 | static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) { | 
| Ted Kremenek | 68957a9 | 2010-08-04 20:01:07 +0000 | [diff] [blame] | 2694 | do { | 
| Ted Kremenek | e8c600f | 2007-08-28 17:02:55 +0000 | [diff] [blame] | 2695 |   // We should only be called for evaluating non-pointer expressions, or | 
 | 2696 |   // expressions with a pointer type that are not used as references but instead | 
 | 2697 |   // are l-values (e.g., DeclRefExpr with a pointer type). | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2698 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2699 |   // Our "symbolic interpreter" is just a dispatch off the currently | 
 | 2700 |   // viewed AST node.  We then recursively traverse the AST by calling | 
 | 2701 |   // EvalAddr and EvalVal appropriately. | 
| Peter Collingbourne | f111d93 | 2011-04-15 00:35:48 +0000 | [diff] [blame] | 2702 |  | 
 | 2703 |   E = E->IgnoreParens(); | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2704 |   switch (E->getStmtClass()) { | 
| Ted Kremenek | 68957a9 | 2010-08-04 20:01:07 +0000 | [diff] [blame] | 2705 |   case Stmt::ImplicitCastExprClass: { | 
 | 2706 |     ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E); | 
| John McCall | 5baba9d | 2010-08-25 10:28:54 +0000 | [diff] [blame] | 2707 |     if (IE->getValueKind() == VK_LValue) { | 
| Ted Kremenek | 68957a9 | 2010-08-04 20:01:07 +0000 | [diff] [blame] | 2708 |       E = IE->getSubExpr(); | 
 | 2709 |       continue; | 
 | 2710 |     } | 
 | 2711 |     return NULL; | 
 | 2712 |   } | 
 | 2713 |  | 
| Douglas Gregor | a2813ce | 2009-10-23 18:54:35 +0000 | [diff] [blame] | 2714 |   case Stmt::DeclRefExprClass: { | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2715 |     // When we hit a DeclRefExpr we are looking at code that refers to a | 
 | 2716 |     // variable's name. If it's not a reference variable we check if it has | 
 | 2717 |     // local storage within the function, and if so, return the expression. | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2718 |     DeclRefExpr *DR = cast<DeclRefExpr>(E); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2719 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2720 |     if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2721 |       if (V->hasLocalStorage()) { | 
 | 2722 |         if (!V->getType()->isReferenceType()) | 
 | 2723 |           return DR; | 
 | 2724 |  | 
 | 2725 |         // Reference variable, follow through to the expression that | 
 | 2726 |         // it points to. | 
 | 2727 |         if (V->hasInit()) { | 
 | 2728 |           // Add the reference variable to the "trail". | 
 | 2729 |           refVars.push_back(DR); | 
 | 2730 |           return EvalVal(V->getInit(), refVars); | 
 | 2731 |         } | 
 | 2732 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2733 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2734 |     return NULL; | 
 | 2735 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2736 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2737 |   case Stmt::UnaryOperatorClass: { | 
 | 2738 |     // The only unary operator that make sense to handle here | 
 | 2739 |     // is Deref.  All others don't resolve to a "name."  This includes | 
 | 2740 |     // handling all sorts of rvalues passed to a unary operator. | 
 | 2741 |     UnaryOperator *U = cast<UnaryOperator>(E); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2742 |  | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 2743 |     if (U->getOpcode() == UO_Deref) | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2744 |       return EvalAddr(U->getSubExpr(), refVars); | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2745 |  | 
 | 2746 |     return NULL; | 
 | 2747 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2748 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2749 |   case Stmt::ArraySubscriptExprClass: { | 
 | 2750 |     // Array subscripts are potential references to data on the stack.  We | 
 | 2751 |     // retrieve the DeclRefExpr* for the array variable if it indeed | 
 | 2752 |     // has local storage. | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2753 |     return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars); | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2754 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2755 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2756 |   case Stmt::ConditionalOperatorClass: { | 
 | 2757 |     // For conditional operators we need to see if either the LHS or RHS are | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2758 |     // non-NULL Expr's.  If one is non-NULL, we return it. | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2759 |     ConditionalOperator *C = cast<ConditionalOperator>(E); | 
 | 2760 |  | 
| Anders Carlsson | 3907323 | 2007-11-30 19:04:31 +0000 | [diff] [blame] | 2761 |     // Handle the GNU extension for missing LHS. | 
 | 2762 |     if (Expr *lhsExpr = C->getLHS()) | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2763 |       if (Expr *LHS = EvalVal(lhsExpr, refVars)) | 
| Anders Carlsson | 3907323 | 2007-11-30 19:04:31 +0000 | [diff] [blame] | 2764 |         return LHS; | 
 | 2765 |  | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2766 |     return EvalVal(C->getRHS(), refVars); | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2767 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2768 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2769 |   // Accesses to members are potential references to data on the stack. | 
| Douglas Gregor | 83f6faf | 2009-08-31 23:41:50 +0000 | [diff] [blame] | 2770 |   case Stmt::MemberExprClass: { | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2771 |     MemberExpr *M = cast<MemberExpr>(E); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2772 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2773 |     // Check for indirect access.  We only want direct field accesses. | 
| Ted Kremenek | a423e81 | 2010-09-02 01:12:13 +0000 | [diff] [blame] | 2774 |     if (M->isArrow()) | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2775 |       return NULL; | 
| Ted Kremenek | a423e81 | 2010-09-02 01:12:13 +0000 | [diff] [blame] | 2776 |  | 
 | 2777 |     // Check whether the member type is itself a reference, in which case | 
 | 2778 |     // we're not going to refer to the member, but to what the member refers to. | 
 | 2779 |     if (M->getMemberDecl()->getType()->isReferenceType()) | 
 | 2780 |       return NULL; | 
 | 2781 |  | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2782 |     return EvalVal(M->getBase(), refVars); | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2783 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2784 |  | 
| Douglas Gregor | 03e8003 | 2011-06-21 17:03:29 +0000 | [diff] [blame] | 2785 |   case Stmt::MaterializeTemporaryExprClass: | 
 | 2786 |     if (Expr *Result = EvalVal( | 
 | 2787 |                           cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(), | 
 | 2788 |                                refVars)) | 
 | 2789 |       return Result; | 
 | 2790 |        | 
 | 2791 |     return E; | 
 | 2792 |  | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2793 |   default: | 
| Argyrios Kyrtzidis | 26e10be | 2010-11-30 22:57:32 +0000 | [diff] [blame] | 2794 |     // Check that we don't return or take the address of a reference to a | 
 | 2795 |     // temporary. This is only useful in C++. | 
 | 2796 |     if (!E->isTypeDependent() && E->isRValue()) | 
 | 2797 |       return E; | 
 | 2798 |  | 
 | 2799 |     // Everything else: we simply don't reason about them. | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2800 |     return NULL; | 
 | 2801 |   } | 
| Ted Kremenek | 68957a9 | 2010-08-04 20:01:07 +0000 | [diff] [blame] | 2802 | } while (true); | 
| Ted Kremenek | 06de276 | 2007-08-17 16:46:58 +0000 | [diff] [blame] | 2803 | } | 
| Ted Kremenek | 588e5eb | 2007-11-25 00:58:00 +0000 | [diff] [blame] | 2804 |  | 
 | 2805 | //===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===// | 
 | 2806 |  | 
 | 2807 | /// Check for comparisons of floating point operands using != and ==. | 
 | 2808 | /// Issue a warning if these are no self-comparisons, as they are not likely | 
 | 2809 | /// to do what the programmer intended. | 
| Richard Trieu | dd22509 | 2011-09-15 21:56:47 +0000 | [diff] [blame] | 2810 | void Sema::CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr *RHS) { | 
| Ted Kremenek | 588e5eb | 2007-11-25 00:58:00 +0000 | [diff] [blame] | 2811 |   bool EmitWarning = true; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2812 |  | 
| Richard Trieu | dd22509 | 2011-09-15 21:56:47 +0000 | [diff] [blame] | 2813 |   Expr* LeftExprSansParen = LHS->IgnoreParenImpCasts(); | 
 | 2814 |   Expr* RightExprSansParen = RHS->IgnoreParenImpCasts(); | 
| Ted Kremenek | 588e5eb | 2007-11-25 00:58:00 +0000 | [diff] [blame] | 2815 |  | 
 | 2816 |   // Special case: check for x == x (which is OK). | 
 | 2817 |   // Do not emit warnings for such cases. | 
 | 2818 |   if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen)) | 
 | 2819 |     if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RightExprSansParen)) | 
 | 2820 |       if (DRL->getDecl() == DRR->getDecl()) | 
 | 2821 |         EmitWarning = false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2822 |  | 
 | 2823 |  | 
| Ted Kremenek | 1b500bb | 2007-11-29 00:59:04 +0000 | [diff] [blame] | 2824 |   // Special case: check for comparisons against literals that can be exactly | 
 | 2825 |   //  represented by APFloat.  In such cases, do not emit a warning.  This | 
 | 2826 |   //  is a heuristic: often comparison against such literals are used to | 
 | 2827 |   //  detect if a value in a variable has not changed.  This clearly can | 
 | 2828 |   //  lead to false negatives. | 
 | 2829 |   if (EmitWarning) { | 
 | 2830 |     if (FloatingLiteral* FLL = dyn_cast<FloatingLiteral>(LeftExprSansParen)) { | 
 | 2831 |       if (FLL->isExact()) | 
 | 2832 |         EmitWarning = false; | 
| Mike Stump | ac5fc7c | 2009-08-04 21:02:39 +0000 | [diff] [blame] | 2833 |     } else | 
| Ted Kremenek | 1b500bb | 2007-11-29 00:59:04 +0000 | [diff] [blame] | 2834 |       if (FloatingLiteral* FLR = dyn_cast<FloatingLiteral>(RightExprSansParen)){ | 
 | 2835 |         if (FLR->isExact()) | 
 | 2836 |           EmitWarning = false; | 
 | 2837 |     } | 
 | 2838 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2839 |  | 
| Ted Kremenek | 588e5eb | 2007-11-25 00:58:00 +0000 | [diff] [blame] | 2840 |   // Check for comparisons with builtin types. | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 2841 |   if (EmitWarning) | 
| Ted Kremenek | 588e5eb | 2007-11-25 00:58:00 +0000 | [diff] [blame] | 2842 |     if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen)) | 
| Douglas Gregor | 3c385e5 | 2009-02-14 18:57:46 +0000 | [diff] [blame] | 2843 |       if (CL->isBuiltinCall(Context)) | 
| Ted Kremenek | 588e5eb | 2007-11-25 00:58:00 +0000 | [diff] [blame] | 2844 |         EmitWarning = false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2845 |  | 
| Sebastian Redl | 0eb2330 | 2009-01-19 00:08:26 +0000 | [diff] [blame] | 2846 |   if (EmitWarning) | 
| Ted Kremenek | 588e5eb | 2007-11-25 00:58:00 +0000 | [diff] [blame] | 2847 |     if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen)) | 
| Douglas Gregor | 3c385e5 | 2009-02-14 18:57:46 +0000 | [diff] [blame] | 2848 |       if (CR->isBuiltinCall(Context)) | 
| Ted Kremenek | 588e5eb | 2007-11-25 00:58:00 +0000 | [diff] [blame] | 2849 |         EmitWarning = false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2850 |  | 
| Ted Kremenek | 588e5eb | 2007-11-25 00:58:00 +0000 | [diff] [blame] | 2851 |   // Emit the diagnostic. | 
 | 2852 |   if (EmitWarning) | 
| Richard Trieu | dd22509 | 2011-09-15 21:56:47 +0000 | [diff] [blame] | 2853 |     Diag(Loc, diag::warn_floatingpoint_eq) | 
 | 2854 |       << LHS->getSourceRange() << RHS->getSourceRange(); | 
| Ted Kremenek | 588e5eb | 2007-11-25 00:58:00 +0000 | [diff] [blame] | 2855 | } | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 2856 |  | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2857 | //===--- CHECK: Integer mixed-sign comparisons (-Wsign-compare) --------===// | 
 | 2858 | //===--- CHECK: Lossy implicit conversions (-Wconversion) --------------===// | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 2859 |  | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2860 | namespace { | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 2861 |  | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2862 | /// Structure recording the 'active' range of an integer-valued | 
 | 2863 | /// expression. | 
 | 2864 | struct IntRange { | 
 | 2865 |   /// The number of bits active in the int. | 
 | 2866 |   unsigned Width; | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 2867 |  | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2868 |   /// True if the int is known not to have negative values. | 
 | 2869 |   bool NonNegative; | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 2870 |  | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2871 |   IntRange(unsigned Width, bool NonNegative) | 
 | 2872 |     : Width(Width), NonNegative(NonNegative) | 
 | 2873 |   {} | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 2874 |  | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 2875 |   /// Returns the range of the bool type. | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2876 |   static IntRange forBoolType() { | 
 | 2877 |     return IntRange(1, true); | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 2878 |   } | 
 | 2879 |  | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 2880 |   /// Returns the range of an opaque value of the given integral type. | 
 | 2881 |   static IntRange forValueOfType(ASTContext &C, QualType T) { | 
 | 2882 |     return forValueOfCanonicalType(C, | 
 | 2883 |                           T->getCanonicalTypeInternal().getTypePtr()); | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 2884 |   } | 
 | 2885 |  | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 2886 |   /// Returns the range of an opaque value of a canonical integral type. | 
 | 2887 |   static IntRange forValueOfCanonicalType(ASTContext &C, const Type *T) { | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2888 |     assert(T->isCanonicalUnqualified()); | 
 | 2889 |  | 
 | 2890 |     if (const VectorType *VT = dyn_cast<VectorType>(T)) | 
 | 2891 |       T = VT->getElementType().getTypePtr(); | 
 | 2892 |     if (const ComplexType *CT = dyn_cast<ComplexType>(T)) | 
 | 2893 |       T = CT->getElementType().getTypePtr(); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 2894 |  | 
| John McCall | 091f23f | 2010-11-09 22:22:12 +0000 | [diff] [blame] | 2895 |     // For enum types, use the known bit width of the enumerators. | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 2896 |     if (const EnumType *ET = dyn_cast<EnumType>(T)) { | 
 | 2897 |       EnumDecl *Enum = ET->getDecl(); | 
| John McCall | 5e1cdac | 2011-10-07 06:10:15 +0000 | [diff] [blame] | 2898 |       if (!Enum->isCompleteDefinition()) | 
| John McCall | 091f23f | 2010-11-09 22:22:12 +0000 | [diff] [blame] | 2899 |         return IntRange(C.getIntWidth(QualType(T, 0)), false); | 
 | 2900 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 2901 |       unsigned NumPositive = Enum->getNumPositiveBits(); | 
 | 2902 |       unsigned NumNegative = Enum->getNumNegativeBits(); | 
 | 2903 |  | 
 | 2904 |       return IntRange(std::max(NumPositive, NumNegative), NumNegative == 0); | 
 | 2905 |     } | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2906 |  | 
 | 2907 |     const BuiltinType *BT = cast<BuiltinType>(T); | 
 | 2908 |     assert(BT->isInteger()); | 
 | 2909 |  | 
 | 2910 |     return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger()); | 
 | 2911 |   } | 
 | 2912 |  | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 2913 |   /// Returns the "target" range of a canonical integral type, i.e. | 
 | 2914 |   /// the range of values expressible in the type. | 
 | 2915 |   /// | 
 | 2916 |   /// This matches forValueOfCanonicalType except that enums have the | 
 | 2917 |   /// full range of their type, not the range of their enumerators. | 
 | 2918 |   static IntRange forTargetOfCanonicalType(ASTContext &C, const Type *T) { | 
 | 2919 |     assert(T->isCanonicalUnqualified()); | 
 | 2920 |  | 
 | 2921 |     if (const VectorType *VT = dyn_cast<VectorType>(T)) | 
 | 2922 |       T = VT->getElementType().getTypePtr(); | 
 | 2923 |     if (const ComplexType *CT = dyn_cast<ComplexType>(T)) | 
 | 2924 |       T = CT->getElementType().getTypePtr(); | 
 | 2925 |     if (const EnumType *ET = dyn_cast<EnumType>(T)) | 
| Douglas Gregor | 69ff26b | 2011-09-08 23:29:05 +0000 | [diff] [blame] | 2926 |       T = C.getCanonicalType(ET->getDecl()->getIntegerType()).getTypePtr(); | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 2927 |  | 
 | 2928 |     const BuiltinType *BT = cast<BuiltinType>(T); | 
 | 2929 |     assert(BT->isInteger()); | 
 | 2930 |  | 
 | 2931 |     return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger()); | 
 | 2932 |   } | 
 | 2933 |  | 
 | 2934 |   /// Returns the supremum of two ranges: i.e. their conservative merge. | 
| John McCall | c0cd21d | 2010-02-23 19:22:29 +0000 | [diff] [blame] | 2935 |   static IntRange join(IntRange L, IntRange R) { | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2936 |     return IntRange(std::max(L.Width, R.Width), | 
| John McCall | 60fad45 | 2010-01-06 22:07:33 +0000 | [diff] [blame] | 2937 |                     L.NonNegative && R.NonNegative); | 
 | 2938 |   } | 
 | 2939 |  | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 2940 |   /// Returns the infinum of two ranges: i.e. their aggressive merge. | 
| John McCall | c0cd21d | 2010-02-23 19:22:29 +0000 | [diff] [blame] | 2941 |   static IntRange meet(IntRange L, IntRange R) { | 
| John McCall | 60fad45 | 2010-01-06 22:07:33 +0000 | [diff] [blame] | 2942 |     return IntRange(std::min(L.Width, R.Width), | 
 | 2943 |                     L.NonNegative || R.NonNegative); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2944 |   } | 
 | 2945 | }; | 
 | 2946 |  | 
 | 2947 | IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) { | 
 | 2948 |   if (value.isSigned() && value.isNegative()) | 
 | 2949 |     return IntRange(value.getMinSignedBits(), false); | 
 | 2950 |  | 
 | 2951 |   if (value.getBitWidth() > MaxWidth) | 
| Jay Foad | 9f71a8f | 2010-12-07 08:25:34 +0000 | [diff] [blame] | 2952 |     value = value.trunc(MaxWidth); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2953 |  | 
 | 2954 |   // isNonNegative() just checks the sign bit without considering | 
 | 2955 |   // signedness. | 
 | 2956 |   return IntRange(value.getActiveBits(), true); | 
 | 2957 | } | 
 | 2958 |  | 
| John McCall | 0acc311 | 2010-01-06 22:57:21 +0000 | [diff] [blame] | 2959 | IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2960 |                        unsigned MaxWidth) { | 
 | 2961 |   if (result.isInt()) | 
 | 2962 |     return GetValueRange(C, result.getInt(), MaxWidth); | 
 | 2963 |  | 
 | 2964 |   if (result.isVector()) { | 
| John McCall | 0acc311 | 2010-01-06 22:57:21 +0000 | [diff] [blame] | 2965 |     IntRange R = GetValueRange(C, result.getVectorElt(0), Ty, MaxWidth); | 
 | 2966 |     for (unsigned i = 1, e = result.getVectorLength(); i != e; ++i) { | 
 | 2967 |       IntRange El = GetValueRange(C, result.getVectorElt(i), Ty, MaxWidth); | 
 | 2968 |       R = IntRange::join(R, El); | 
 | 2969 |     } | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2970 |     return R; | 
 | 2971 |   } | 
 | 2972 |  | 
 | 2973 |   if (result.isComplexInt()) { | 
 | 2974 |     IntRange R = GetValueRange(C, result.getComplexIntReal(), MaxWidth); | 
 | 2975 |     IntRange I = GetValueRange(C, result.getComplexIntImag(), MaxWidth); | 
 | 2976 |     return IntRange::join(R, I); | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 2977 |   } | 
 | 2978 |  | 
 | 2979 |   // This can happen with lossless casts to intptr_t of "based" lvalues. | 
 | 2980 |   // Assume it might use arbitrary bits. | 
| John McCall | 0acc311 | 2010-01-06 22:57:21 +0000 | [diff] [blame] | 2981 |   // FIXME: The only reason we need to pass the type in here is to get | 
 | 2982 |   // the sign right on this one case.  It would be nice if APValue | 
 | 2983 |   // preserved this. | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2984 |   assert(result.isLValue()); | 
| Douglas Gregor | 5e9ebb3 | 2011-05-21 16:28:01 +0000 | [diff] [blame] | 2985 |   return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType()); | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 2986 | } | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2987 |  | 
 | 2988 | /// Pseudo-evaluate the given integer expression, estimating the | 
 | 2989 | /// range of values it might take. | 
 | 2990 | /// | 
 | 2991 | /// \param MaxWidth - the width to which the value will be truncated | 
 | 2992 | IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { | 
 | 2993 |   E = E->IgnoreParens(); | 
 | 2994 |  | 
 | 2995 |   // Try a full evaluation first. | 
 | 2996 |   Expr::EvalResult result; | 
| Richard Smith | 51f4708 | 2011-10-29 00:50:52 +0000 | [diff] [blame] | 2997 |   if (E->EvaluateAsRValue(result, C)) | 
| John McCall | 0acc311 | 2010-01-06 22:57:21 +0000 | [diff] [blame] | 2998 |     return GetValueRange(C, result.Val, E->getType(), MaxWidth); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 2999 |  | 
 | 3000 |   // I think we only want to look through implicit casts here; if the | 
 | 3001 |   // user has an explicit widening cast, we should treat the value as | 
 | 3002 |   // being of the new, wider type. | 
 | 3003 |   if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) { | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3004 |     if (CE->getCastKind() == CK_NoOp) | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3005 |       return GetExprRange(C, CE->getSubExpr(), MaxWidth); | 
 | 3006 |  | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 3007 |     IntRange OutputTypeRange = IntRange::forValueOfType(C, CE->getType()); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3008 |  | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3009 |     bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast); | 
| John McCall | 60fad45 | 2010-01-06 22:07:33 +0000 | [diff] [blame] | 3010 |  | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3011 |     // Assume that non-integer casts can span the full range of the type. | 
| John McCall | 60fad45 | 2010-01-06 22:07:33 +0000 | [diff] [blame] | 3012 |     if (!isIntegerCast) | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3013 |       return OutputTypeRange; | 
 | 3014 |  | 
 | 3015 |     IntRange SubRange | 
 | 3016 |       = GetExprRange(C, CE->getSubExpr(), | 
 | 3017 |                      std::min(MaxWidth, OutputTypeRange.Width)); | 
 | 3018 |  | 
 | 3019 |     // Bail out if the subexpr's range is as wide as the cast type. | 
 | 3020 |     if (SubRange.Width >= OutputTypeRange.Width) | 
 | 3021 |       return OutputTypeRange; | 
 | 3022 |  | 
 | 3023 |     // Otherwise, we take the smaller width, and we're non-negative if | 
 | 3024 |     // either the output type or the subexpr is. | 
 | 3025 |     return IntRange(SubRange.Width, | 
 | 3026 |                     SubRange.NonNegative || OutputTypeRange.NonNegative); | 
 | 3027 |   } | 
 | 3028 |  | 
 | 3029 |   if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { | 
 | 3030 |     // If we can fold the condition, just take that operand. | 
 | 3031 |     bool CondResult; | 
 | 3032 |     if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C)) | 
 | 3033 |       return GetExprRange(C, CondResult ? CO->getTrueExpr() | 
 | 3034 |                                         : CO->getFalseExpr(), | 
 | 3035 |                           MaxWidth); | 
 | 3036 |  | 
 | 3037 |     // Otherwise, conservatively merge. | 
 | 3038 |     IntRange L = GetExprRange(C, CO->getTrueExpr(), MaxWidth); | 
 | 3039 |     IntRange R = GetExprRange(C, CO->getFalseExpr(), MaxWidth); | 
 | 3040 |     return IntRange::join(L, R); | 
 | 3041 |   } | 
 | 3042 |  | 
 | 3043 |   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { | 
 | 3044 |     switch (BO->getOpcode()) { | 
 | 3045 |  | 
 | 3046 |     // Boolean-valued operations are single-bit and positive. | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3047 |     case BO_LAnd: | 
 | 3048 |     case BO_LOr: | 
 | 3049 |     case BO_LT: | 
 | 3050 |     case BO_GT: | 
 | 3051 |     case BO_LE: | 
 | 3052 |     case BO_GE: | 
 | 3053 |     case BO_EQ: | 
 | 3054 |     case BO_NE: | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3055 |       return IntRange::forBoolType(); | 
 | 3056 |  | 
| John McCall | 862ff87 | 2011-07-13 06:35:24 +0000 | [diff] [blame] | 3057 |     // The type of the assignments is the type of the LHS, so the RHS | 
 | 3058 |     // is not necessarily the same type. | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3059 |     case BO_MulAssign: | 
 | 3060 |     case BO_DivAssign: | 
 | 3061 |     case BO_RemAssign: | 
 | 3062 |     case BO_AddAssign: | 
 | 3063 |     case BO_SubAssign: | 
| John McCall | 862ff87 | 2011-07-13 06:35:24 +0000 | [diff] [blame] | 3064 |     case BO_XorAssign: | 
 | 3065 |     case BO_OrAssign: | 
 | 3066 |       // TODO: bitfields? | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 3067 |       return IntRange::forValueOfType(C, E->getType()); | 
| John McCall | c0cd21d | 2010-02-23 19:22:29 +0000 | [diff] [blame] | 3068 |  | 
| John McCall | 862ff87 | 2011-07-13 06:35:24 +0000 | [diff] [blame] | 3069 |     // Simple assignments just pass through the RHS, which will have | 
 | 3070 |     // been coerced to the LHS type. | 
 | 3071 |     case BO_Assign: | 
 | 3072 |       // TODO: bitfields? | 
 | 3073 |       return GetExprRange(C, BO->getRHS(), MaxWidth); | 
 | 3074 |  | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3075 |     // Operations with opaque sources are black-listed. | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3076 |     case BO_PtrMemD: | 
 | 3077 |     case BO_PtrMemI: | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 3078 |       return IntRange::forValueOfType(C, E->getType()); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3079 |  | 
| John McCall | 60fad45 | 2010-01-06 22:07:33 +0000 | [diff] [blame] | 3080 |     // Bitwise-and uses the *infinum* of the two source ranges. | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3081 |     case BO_And: | 
 | 3082 |     case BO_AndAssign: | 
| John McCall | 60fad45 | 2010-01-06 22:07:33 +0000 | [diff] [blame] | 3083 |       return IntRange::meet(GetExprRange(C, BO->getLHS(), MaxWidth), | 
 | 3084 |                             GetExprRange(C, BO->getRHS(), MaxWidth)); | 
 | 3085 |  | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3086 |     // Left shift gets black-listed based on a judgement call. | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3087 |     case BO_Shl: | 
| John McCall | 3aae609 | 2010-04-07 01:14:35 +0000 | [diff] [blame] | 3088 |       // ...except that we want to treat '1 << (blah)' as logically | 
 | 3089 |       // positive.  It's an important idiom. | 
 | 3090 |       if (IntegerLiteral *I | 
 | 3091 |             = dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) { | 
 | 3092 |         if (I->getValue() == 1) { | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 3093 |           IntRange R = IntRange::forValueOfType(C, E->getType()); | 
| John McCall | 3aae609 | 2010-04-07 01:14:35 +0000 | [diff] [blame] | 3094 |           return IntRange(R.Width, /*NonNegative*/ true); | 
 | 3095 |         } | 
 | 3096 |       } | 
 | 3097 |       // fallthrough | 
 | 3098 |  | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3099 |     case BO_ShlAssign: | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 3100 |       return IntRange::forValueOfType(C, E->getType()); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3101 |  | 
| John McCall | 60fad45 | 2010-01-06 22:07:33 +0000 | [diff] [blame] | 3102 |     // Right shift by a constant can narrow its left argument. | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3103 |     case BO_Shr: | 
 | 3104 |     case BO_ShrAssign: { | 
| John McCall | 60fad45 | 2010-01-06 22:07:33 +0000 | [diff] [blame] | 3105 |       IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth); | 
 | 3106 |  | 
 | 3107 |       // If the shift amount is a positive constant, drop the width by | 
 | 3108 |       // that much. | 
 | 3109 |       llvm::APSInt shift; | 
 | 3110 |       if (BO->getRHS()->isIntegerConstantExpr(shift, C) && | 
 | 3111 |           shift.isNonNegative()) { | 
 | 3112 |         unsigned zext = shift.getZExtValue(); | 
 | 3113 |         if (zext >= L.Width) | 
 | 3114 |           L.Width = (L.NonNegative ? 0 : 1); | 
 | 3115 |         else | 
 | 3116 |           L.Width -= zext; | 
 | 3117 |       } | 
 | 3118 |  | 
 | 3119 |       return L; | 
 | 3120 |     } | 
 | 3121 |  | 
 | 3122 |     // Comma acts as its right operand. | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3123 |     case BO_Comma: | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3124 |       return GetExprRange(C, BO->getRHS(), MaxWidth); | 
 | 3125 |  | 
| John McCall | 60fad45 | 2010-01-06 22:07:33 +0000 | [diff] [blame] | 3126 |     // Black-list pointer subtractions. | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3127 |     case BO_Sub: | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3128 |       if (BO->getLHS()->getType()->isPointerType()) | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 3129 |         return IntRange::forValueOfType(C, E->getType()); | 
| John McCall | 00fe761 | 2011-07-14 22:39:48 +0000 | [diff] [blame] | 3130 |       break; | 
| Ted Kremenek | 4e4b30e | 2010-02-16 01:46:59 +0000 | [diff] [blame] | 3131 |  | 
| John McCall | 00fe761 | 2011-07-14 22:39:48 +0000 | [diff] [blame] | 3132 |     // The width of a division result is mostly determined by the size | 
 | 3133 |     // of the LHS. | 
 | 3134 |     case BO_Div: { | 
 | 3135 |       // Don't 'pre-truncate' the operands. | 
 | 3136 |       unsigned opWidth = C.getIntWidth(E->getType()); | 
 | 3137 |       IntRange L = GetExprRange(C, BO->getLHS(), opWidth); | 
 | 3138 |  | 
 | 3139 |       // If the divisor is constant, use that. | 
 | 3140 |       llvm::APSInt divisor; | 
 | 3141 |       if (BO->getRHS()->isIntegerConstantExpr(divisor, C)) { | 
 | 3142 |         unsigned log2 = divisor.logBase2(); // floor(log_2(divisor)) | 
 | 3143 |         if (log2 >= L.Width) | 
 | 3144 |           L.Width = (L.NonNegative ? 0 : 1); | 
 | 3145 |         else | 
 | 3146 |           L.Width = std::min(L.Width - log2, MaxWidth); | 
 | 3147 |         return L; | 
 | 3148 |       } | 
 | 3149 |  | 
 | 3150 |       // Otherwise, just use the LHS's width. | 
 | 3151 |       IntRange R = GetExprRange(C, BO->getRHS(), opWidth); | 
 | 3152 |       return IntRange(L.Width, L.NonNegative && R.NonNegative); | 
 | 3153 |     } | 
 | 3154 |  | 
 | 3155 |     // The result of a remainder can't be larger than the result of | 
 | 3156 |     // either side. | 
 | 3157 |     case BO_Rem: { | 
 | 3158 |       // Don't 'pre-truncate' the operands. | 
 | 3159 |       unsigned opWidth = C.getIntWidth(E->getType()); | 
 | 3160 |       IntRange L = GetExprRange(C, BO->getLHS(), opWidth); | 
 | 3161 |       IntRange R = GetExprRange(C, BO->getRHS(), opWidth); | 
 | 3162 |  | 
 | 3163 |       IntRange meet = IntRange::meet(L, R); | 
 | 3164 |       meet.Width = std::min(meet.Width, MaxWidth); | 
 | 3165 |       return meet; | 
 | 3166 |     } | 
 | 3167 |  | 
 | 3168 |     // The default behavior is okay for these. | 
 | 3169 |     case BO_Mul: | 
 | 3170 |     case BO_Add: | 
 | 3171 |     case BO_Xor: | 
 | 3172 |     case BO_Or: | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3173 |       break; | 
 | 3174 |     } | 
 | 3175 |  | 
| John McCall | 00fe761 | 2011-07-14 22:39:48 +0000 | [diff] [blame] | 3176 |     // The default case is to treat the operation as if it were closed | 
 | 3177 |     // on the narrowest type that encompasses both operands. | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3178 |     IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth); | 
 | 3179 |     IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth); | 
 | 3180 |     return IntRange::join(L, R); | 
 | 3181 |   } | 
 | 3182 |  | 
 | 3183 |   if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { | 
 | 3184 |     switch (UO->getOpcode()) { | 
 | 3185 |     // Boolean-valued operations are white-listed. | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3186 |     case UO_LNot: | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3187 |       return IntRange::forBoolType(); | 
 | 3188 |  | 
 | 3189 |     // Operations with opaque sources are black-listed. | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3190 |     case UO_Deref: | 
 | 3191 |     case UO_AddrOf: // should be impossible | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 3192 |       return IntRange::forValueOfType(C, E->getType()); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3193 |  | 
 | 3194 |     default: | 
 | 3195 |       return GetExprRange(C, UO->getSubExpr(), MaxWidth); | 
 | 3196 |     } | 
 | 3197 |   } | 
| Douglas Gregor | 8ecdb65 | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 3198 |    | 
 | 3199 |   if (dyn_cast<OffsetOfExpr>(E)) { | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 3200 |     IntRange::forValueOfType(C, E->getType()); | 
| Douglas Gregor | 8ecdb65 | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 3201 |   } | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3202 |  | 
| Richard Smith | a6b8b2c | 2011-10-10 18:28:20 +0000 | [diff] [blame] | 3203 |   if (FieldDecl *BitField = E->getBitField()) | 
 | 3204 |     return IntRange(BitField->getBitWidthValue(C), | 
| Douglas Gregor | 5e9ebb3 | 2011-05-21 16:28:01 +0000 | [diff] [blame] | 3205 |                     BitField->getType()->isUnsignedIntegerOrEnumerationType()); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3206 |  | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 3207 |   return IntRange::forValueOfType(C, E->getType()); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3208 | } | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3209 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3210 | IntRange GetExprRange(ASTContext &C, Expr *E) { | 
 | 3211 |   return GetExprRange(C, E, C.getIntWidth(E->getType())); | 
 | 3212 | } | 
 | 3213 |  | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3214 | /// Checks whether the given value, which currently has the given | 
 | 3215 | /// source semantics, has the same value when coerced through the | 
 | 3216 | /// target semantics. | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3217 | bool IsSameFloatAfterCast(const llvm::APFloat &value, | 
 | 3218 |                           const llvm::fltSemantics &Src, | 
 | 3219 |                           const llvm::fltSemantics &Tgt) { | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3220 |   llvm::APFloat truncated = value; | 
 | 3221 |  | 
 | 3222 |   bool ignored; | 
 | 3223 |   truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored); | 
 | 3224 |   truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored); | 
 | 3225 |  | 
 | 3226 |   return truncated.bitwiseIsEqual(value); | 
 | 3227 | } | 
 | 3228 |  | 
 | 3229 | /// Checks whether the given value, which currently has the given | 
 | 3230 | /// source semantics, has the same value when coerced through the | 
 | 3231 | /// target semantics. | 
 | 3232 | /// | 
 | 3233 | /// The value might be a vector of floats (or a complex number). | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3234 | bool IsSameFloatAfterCast(const APValue &value, | 
 | 3235 |                           const llvm::fltSemantics &Src, | 
 | 3236 |                           const llvm::fltSemantics &Tgt) { | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3237 |   if (value.isFloat()) | 
 | 3238 |     return IsSameFloatAfterCast(value.getFloat(), Src, Tgt); | 
 | 3239 |  | 
 | 3240 |   if (value.isVector()) { | 
 | 3241 |     for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i) | 
 | 3242 |       if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt)) | 
 | 3243 |         return false; | 
 | 3244 |     return true; | 
 | 3245 |   } | 
 | 3246 |  | 
 | 3247 |   assert(value.isComplexFloat()); | 
 | 3248 |   return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) && | 
 | 3249 |           IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt)); | 
 | 3250 | } | 
 | 3251 |  | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3252 | void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3253 |  | 
| Ted Kremenek | e3b159c | 2010-09-23 21:43:44 +0000 | [diff] [blame] | 3254 | static bool IsZero(Sema &S, Expr *E) { | 
 | 3255 |   // Suppress cases where we are comparing against an enum constant. | 
 | 3256 |   if (const DeclRefExpr *DR = | 
 | 3257 |       dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) | 
 | 3258 |     if (isa<EnumConstantDecl>(DR->getDecl())) | 
 | 3259 |       return false; | 
 | 3260 |  | 
 | 3261 |   // Suppress cases where the '0' value is expanded from a macro. | 
 | 3262 |   if (E->getLocStart().isMacroID()) | 
 | 3263 |     return false; | 
 | 3264 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3265 |   llvm::APSInt Value; | 
 | 3266 |   return E->isIntegerConstantExpr(Value, S.Context) && Value == 0; | 
 | 3267 | } | 
 | 3268 |  | 
| John McCall | 372e103 | 2010-10-06 00:25:24 +0000 | [diff] [blame] | 3269 | static bool HasEnumType(Expr *E) { | 
 | 3270 |   // Strip off implicit integral promotions. | 
 | 3271 |   while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { | 
| Argyrios Kyrtzidis | 63b57ae | 2010-10-07 21:52:18 +0000 | [diff] [blame] | 3272 |     if (ICE->getCastKind() != CK_IntegralCast && | 
 | 3273 |         ICE->getCastKind() != CK_NoOp) | 
| John McCall | 372e103 | 2010-10-06 00:25:24 +0000 | [diff] [blame] | 3274 |       break; | 
| Argyrios Kyrtzidis | 63b57ae | 2010-10-07 21:52:18 +0000 | [diff] [blame] | 3275 |     E = ICE->getSubExpr(); | 
| John McCall | 372e103 | 2010-10-06 00:25:24 +0000 | [diff] [blame] | 3276 |   } | 
 | 3277 |  | 
 | 3278 |   return E->getType()->isEnumeralType(); | 
 | 3279 | } | 
 | 3280 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3281 | void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3282 |   BinaryOperatorKind op = E->getOpcode(); | 
| Douglas Gregor | 14af91a | 2010-12-21 07:22:56 +0000 | [diff] [blame] | 3283 |   if (E->isValueDependent()) | 
 | 3284 |     return; | 
 | 3285 |  | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3286 |   if (op == BO_LT && IsZero(S, E->getRHS())) { | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3287 |     S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison) | 
| John McCall | 372e103 | 2010-10-06 00:25:24 +0000 | [diff] [blame] | 3288 |       << "< 0" << "false" << HasEnumType(E->getLHS()) | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3289 |       << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3290 |   } else if (op == BO_GE && IsZero(S, E->getRHS())) { | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3291 |     S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison) | 
| John McCall | 372e103 | 2010-10-06 00:25:24 +0000 | [diff] [blame] | 3292 |       << ">= 0" << "true" << HasEnumType(E->getLHS()) | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3293 |       << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3294 |   } else if (op == BO_GT && IsZero(S, E->getLHS())) { | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3295 |     S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison) | 
| John McCall | 372e103 | 2010-10-06 00:25:24 +0000 | [diff] [blame] | 3296 |       << "0 >" << "false" << HasEnumType(E->getRHS()) | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3297 |       << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 3298 |   } else if (op == BO_LE && IsZero(S, E->getLHS())) { | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3299 |     S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison) | 
| John McCall | 372e103 | 2010-10-06 00:25:24 +0000 | [diff] [blame] | 3300 |       << "0 <=" << "true" << HasEnumType(E->getRHS()) | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3301 |       << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); | 
 | 3302 |   } | 
 | 3303 | } | 
 | 3304 |  | 
 | 3305 | /// Analyze the operands of the given comparison.  Implements the | 
 | 3306 | /// fallback case from AnalyzeComparison. | 
 | 3307 | void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3308 |   AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); | 
 | 3309 |   AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3310 | } | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3311 |  | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 3312 | /// \brief Implements -Wsign-compare. | 
 | 3313 | /// | 
| Richard Trieu | dd22509 | 2011-09-15 21:56:47 +0000 | [diff] [blame] | 3314 | /// \param E the binary operator to check for warnings | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3315 | void AnalyzeComparison(Sema &S, BinaryOperator *E) { | 
 | 3316 |   // The type the comparison is being performed in. | 
 | 3317 |   QualType T = E->getLHS()->getType(); | 
 | 3318 |   assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType()) | 
 | 3319 |          && "comparison with mismatched types"); | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 3320 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3321 |   // We don't do anything special if this isn't an unsigned integral | 
 | 3322 |   // comparison:  we're only interested in integral comparisons, and | 
 | 3323 |   // signed comparisons only happen in cases we don't care to warn about. | 
| Douglas Gregor | 3e026e3 | 2011-02-19 22:34:59 +0000 | [diff] [blame] | 3324 |   // | 
 | 3325 |   // We also don't care about value-dependent expressions or expressions | 
 | 3326 |   // whose result is a constant. | 
 | 3327 |   if (!T->hasUnsignedIntegerRepresentation() | 
 | 3328 |       || E->isValueDependent() || E->isIntegerConstantExpr(S.Context)) | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3329 |     return AnalyzeImpConvsInComparison(S, E); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3330 |  | 
| Richard Trieu | dd22509 | 2011-09-15 21:56:47 +0000 | [diff] [blame] | 3331 |   Expr *LHS = E->getLHS()->IgnoreParenImpCasts(); | 
 | 3332 |   Expr *RHS = E->getRHS()->IgnoreParenImpCasts(); | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 3333 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3334 |   // Check to see if one of the (unmodified) operands is of different | 
 | 3335 |   // signedness. | 
 | 3336 |   Expr *signedOperand, *unsignedOperand; | 
| Richard Trieu | dd22509 | 2011-09-15 21:56:47 +0000 | [diff] [blame] | 3337 |   if (LHS->getType()->hasSignedIntegerRepresentation()) { | 
 | 3338 |     assert(!RHS->getType()->hasSignedIntegerRepresentation() && | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3339 |            "unsigned comparison between two signed integer expressions?"); | 
| Richard Trieu | dd22509 | 2011-09-15 21:56:47 +0000 | [diff] [blame] | 3340 |     signedOperand = LHS; | 
 | 3341 |     unsignedOperand = RHS; | 
 | 3342 |   } else if (RHS->getType()->hasSignedIntegerRepresentation()) { | 
 | 3343 |     signedOperand = RHS; | 
 | 3344 |     unsignedOperand = LHS; | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 3345 |   } else { | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3346 |     CheckTrivialUnsignedComparison(S, E); | 
 | 3347 |     return AnalyzeImpConvsInComparison(S, E); | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 3348 |   } | 
 | 3349 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3350 |   // Otherwise, calculate the effective range of the signed operand. | 
 | 3351 |   IntRange signedRange = GetExprRange(S.Context, signedOperand); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3352 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3353 |   // Go ahead and analyze implicit conversions in the operands.  Note | 
 | 3354 |   // that we skip the implicit conversions on both sides. | 
| Richard Trieu | dd22509 | 2011-09-15 21:56:47 +0000 | [diff] [blame] | 3355 |   AnalyzeImplicitConversions(S, LHS, E->getOperatorLoc()); | 
 | 3356 |   AnalyzeImplicitConversions(S, RHS, E->getOperatorLoc()); | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 3357 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3358 |   // If the signed range is non-negative, -Wsign-compare won't fire, | 
 | 3359 |   // but we should still check for comparisons which are always true | 
 | 3360 |   // or false. | 
 | 3361 |   if (signedRange.NonNegative) | 
 | 3362 |     return CheckTrivialUnsignedComparison(S, E); | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 3363 |  | 
 | 3364 |   // For (in)equality comparisons, if the unsigned operand is a | 
 | 3365 |   // constant which cannot collide with a overflowed signed operand, | 
 | 3366 |   // then reinterpreting the signed operand as unsigned will not | 
 | 3367 |   // change the result of the comparison. | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3368 |   if (E->isEqualityOp()) { | 
 | 3369 |     unsigned comparisonWidth = S.Context.getIntWidth(T); | 
 | 3370 |     IntRange unsignedRange = GetExprRange(S.Context, unsignedOperand); | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 3371 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3372 |     // We should never be unable to prove that the unsigned operand is | 
 | 3373 |     // non-negative. | 
 | 3374 |     assert(unsignedRange.NonNegative && "unsigned range includes negative?"); | 
 | 3375 |  | 
 | 3376 |     if (unsignedRange.Width < comparisonWidth) | 
 | 3377 |       return; | 
 | 3378 |   } | 
 | 3379 |  | 
 | 3380 |   S.Diag(E->getOperatorLoc(), diag::warn_mixed_sign_comparison) | 
| Richard Trieu | dd22509 | 2011-09-15 21:56:47 +0000 | [diff] [blame] | 3381 |     << LHS->getType() << RHS->getType() | 
 | 3382 |     << LHS->getSourceRange() << RHS->getSourceRange(); | 
| John McCall | ba26e58 | 2010-01-04 23:21:16 +0000 | [diff] [blame] | 3383 | } | 
 | 3384 |  | 
| John McCall | 15d7d12 | 2010-11-11 03:21:53 +0000 | [diff] [blame] | 3385 | /// Analyzes an attempt to assign the given value to a bitfield. | 
 | 3386 | /// | 
 | 3387 | /// Returns true if there was something fishy about the attempt. | 
 | 3388 | bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, | 
 | 3389 |                                SourceLocation InitLoc) { | 
 | 3390 |   assert(Bitfield->isBitField()); | 
 | 3391 |   if (Bitfield->isInvalidDecl()) | 
 | 3392 |     return false; | 
 | 3393 |  | 
| John McCall | 91b6014 | 2010-11-11 05:33:51 +0000 | [diff] [blame] | 3394 |   // White-list bool bitfields. | 
 | 3395 |   if (Bitfield->getType()->isBooleanType()) | 
 | 3396 |     return false; | 
 | 3397 |  | 
| Douglas Gregor | 46ff303 | 2011-02-04 13:09:01 +0000 | [diff] [blame] | 3398 |   // Ignore value- or type-dependent expressions. | 
 | 3399 |   if (Bitfield->getBitWidth()->isValueDependent() || | 
 | 3400 |       Bitfield->getBitWidth()->isTypeDependent() || | 
 | 3401 |       Init->isValueDependent() || | 
 | 3402 |       Init->isTypeDependent()) | 
 | 3403 |     return false; | 
 | 3404 |  | 
| John McCall | 15d7d12 | 2010-11-11 03:21:53 +0000 | [diff] [blame] | 3405 |   Expr *OriginalInit = Init->IgnoreParenImpCasts(); | 
 | 3406 |  | 
| John McCall | 15d7d12 | 2010-11-11 03:21:53 +0000 | [diff] [blame] | 3407 |   Expr::EvalResult InitValue; | 
| Richard Smith | 51f4708 | 2011-10-29 00:50:52 +0000 | [diff] [blame] | 3408 |   if (!OriginalInit->EvaluateAsRValue(InitValue, S.Context) || | 
| John McCall | 15d7d12 | 2010-11-11 03:21:53 +0000 | [diff] [blame] | 3409 |       !InitValue.Val.isInt()) | 
 | 3410 |     return false; | 
 | 3411 |  | 
 | 3412 |   const llvm::APSInt &Value = InitValue.Val.getInt(); | 
 | 3413 |   unsigned OriginalWidth = Value.getBitWidth(); | 
| Richard Smith | a6b8b2c | 2011-10-10 18:28:20 +0000 | [diff] [blame] | 3414 |   unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); | 
| John McCall | 15d7d12 | 2010-11-11 03:21:53 +0000 | [diff] [blame] | 3415 |  | 
 | 3416 |   if (OriginalWidth <= FieldWidth) | 
 | 3417 |     return false; | 
 | 3418 |  | 
| Jay Foad | 9f71a8f | 2010-12-07 08:25:34 +0000 | [diff] [blame] | 3419 |   llvm::APSInt TruncatedValue = Value.trunc(FieldWidth); | 
| John McCall | 15d7d12 | 2010-11-11 03:21:53 +0000 | [diff] [blame] | 3420 |  | 
 | 3421 |   // It's fairly common to write values into signed bitfields | 
 | 3422 |   // that, if sign-extended, would end up becoming a different | 
 | 3423 |   // value.  We don't want to warn about that. | 
 | 3424 |   if (Value.isSigned() && Value.isNegative()) | 
| Jay Foad | 9f71a8f | 2010-12-07 08:25:34 +0000 | [diff] [blame] | 3425 |     TruncatedValue = TruncatedValue.sext(OriginalWidth); | 
| John McCall | 15d7d12 | 2010-11-11 03:21:53 +0000 | [diff] [blame] | 3426 |   else | 
| Jay Foad | 9f71a8f | 2010-12-07 08:25:34 +0000 | [diff] [blame] | 3427 |     TruncatedValue = TruncatedValue.zext(OriginalWidth); | 
| John McCall | 15d7d12 | 2010-11-11 03:21:53 +0000 | [diff] [blame] | 3428 |  | 
 | 3429 |   if (Value == TruncatedValue) | 
 | 3430 |     return false; | 
 | 3431 |  | 
 | 3432 |   std::string PrettyValue = Value.toString(10); | 
 | 3433 |   std::string PrettyTrunc = TruncatedValue.toString(10); | 
 | 3434 |  | 
 | 3435 |   S.Diag(InitLoc, diag::warn_impcast_bitfield_precision_constant) | 
 | 3436 |     << PrettyValue << PrettyTrunc << OriginalInit->getType() | 
 | 3437 |     << Init->getSourceRange(); | 
 | 3438 |  | 
 | 3439 |   return true; | 
 | 3440 | } | 
 | 3441 |  | 
| John McCall | beb22aa | 2010-11-09 23:24:47 +0000 | [diff] [blame] | 3442 | /// Analyze the given simple or compound assignment for warning-worthy | 
 | 3443 | /// operations. | 
 | 3444 | void AnalyzeAssignment(Sema &S, BinaryOperator *E) { | 
 | 3445 |   // Just recurse on the LHS. | 
 | 3446 |   AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); | 
 | 3447 |  | 
 | 3448 |   // We want to recurse on the RHS as normal unless we're assigning to | 
 | 3449 |   // a bitfield. | 
 | 3450 |   if (FieldDecl *Bitfield = E->getLHS()->getBitField()) { | 
| John McCall | 15d7d12 | 2010-11-11 03:21:53 +0000 | [diff] [blame] | 3451 |     if (AnalyzeBitFieldAssignment(S, Bitfield, E->getRHS(), | 
 | 3452 |                                   E->getOperatorLoc())) { | 
 | 3453 |       // Recurse, ignoring any implicit conversions on the RHS. | 
 | 3454 |       return AnalyzeImplicitConversions(S, E->getRHS()->IgnoreParenImpCasts(), | 
 | 3455 |                                         E->getOperatorLoc()); | 
| John McCall | beb22aa | 2010-11-09 23:24:47 +0000 | [diff] [blame] | 3456 |     } | 
 | 3457 |   } | 
 | 3458 |  | 
 | 3459 |   AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); | 
 | 3460 | } | 
 | 3461 |  | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3462 | /// Diagnose an implicit cast;  purely a helper for CheckImplicitConversion. | 
| Douglas Gregor | 5a5b38f | 2011-03-12 00:14:31 +0000 | [diff] [blame] | 3463 | void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T,  | 
 | 3464 |                      SourceLocation CContext, unsigned diag) { | 
 | 3465 |   S.Diag(E->getExprLoc(), diag) | 
 | 3466 |     << SourceType << T << E->getSourceRange() << SourceRange(CContext); | 
 | 3467 | } | 
 | 3468 |  | 
| Chandler Carruth | e1b02e0 | 2011-04-05 06:47:57 +0000 | [diff] [blame] | 3469 | /// Diagnose an implicit cast;  purely a helper for CheckImplicitConversion. | 
 | 3470 | void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, | 
 | 3471 |                      unsigned diag) { | 
 | 3472 |   DiagnoseImpCast(S, E, E->getType(), T, CContext, diag); | 
 | 3473 | } | 
 | 3474 |  | 
| Matt Beaumont-Gay | 9ce6377 | 2011-10-14 15:36:25 +0000 | [diff] [blame] | 3475 | /// Diagnose an implicit cast from a literal expression. Does not warn when the | 
 | 3476 | /// cast wouldn't lose information. | 
| Chandler Carruth | f65076e | 2011-04-10 08:36:24 +0000 | [diff] [blame] | 3477 | void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, | 
 | 3478 |                                     SourceLocation CContext) { | 
| Matt Beaumont-Gay | 9ce6377 | 2011-10-14 15:36:25 +0000 | [diff] [blame] | 3479 |   // Try to convert the literal exactly to an integer. If we can, don't warn. | 
| Chandler Carruth | f65076e | 2011-04-10 08:36:24 +0000 | [diff] [blame] | 3480 |   bool isExact = false; | 
| Matt Beaumont-Gay | 9ce6377 | 2011-10-14 15:36:25 +0000 | [diff] [blame] | 3481 |   const llvm::APFloat &Value = FL->getValue(); | 
| Jeffrey Yasskin | 3e1ef78 | 2011-07-15 17:03:07 +0000 | [diff] [blame] | 3482 |   llvm::APSInt IntegerValue(S.Context.getIntWidth(T), | 
 | 3483 |                             T->hasUnsignedIntegerRepresentation()); | 
 | 3484 |   if (Value.convertToInteger(IntegerValue, | 
| Chandler Carruth | f65076e | 2011-04-10 08:36:24 +0000 | [diff] [blame] | 3485 |                              llvm::APFloat::rmTowardZero, &isExact) | 
| Matt Beaumont-Gay | 9ce6377 | 2011-10-14 15:36:25 +0000 | [diff] [blame] | 3486 |       == llvm::APFloat::opOK && isExact) | 
| Chandler Carruth | f65076e | 2011-04-10 08:36:24 +0000 | [diff] [blame] | 3487 |     return; | 
 | 3488 |  | 
| Matt Beaumont-Gay | 9ce6377 | 2011-10-14 15:36:25 +0000 | [diff] [blame] | 3489 |   S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) | 
 | 3490 |     << FL->getType() << T << FL->getSourceRange() << SourceRange(CContext); | 
| Chandler Carruth | f65076e | 2011-04-10 08:36:24 +0000 | [diff] [blame] | 3491 | } | 
 | 3492 |  | 
| John McCall | 091f23f | 2010-11-09 22:22:12 +0000 | [diff] [blame] | 3493 | std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { | 
 | 3494 |   if (!Range.Width) return "0"; | 
 | 3495 |  | 
 | 3496 |   llvm::APSInt ValueInRange = Value; | 
 | 3497 |   ValueInRange.setIsSigned(!Range.NonNegative); | 
| Jay Foad | 9f71a8f | 2010-12-07 08:25:34 +0000 | [diff] [blame] | 3498 |   ValueInRange = ValueInRange.trunc(Range.Width); | 
| John McCall | 091f23f | 2010-11-09 22:22:12 +0000 | [diff] [blame] | 3499 |   return ValueInRange.toString(10); | 
 | 3500 | } | 
 | 3501 |  | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3502 | static bool isFromSystemMacro(Sema &S, SourceLocation loc) { | 
 | 3503 |   SourceManager &smgr = S.Context.getSourceManager(); | 
 | 3504 |   return loc.isMacroID() && smgr.isInSystemHeader(smgr.getSpellingLoc(loc)); | 
 | 3505 | } | 
| Chandler Carruth | f65076e | 2011-04-10 08:36:24 +0000 | [diff] [blame] | 3506 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3507 | void CheckImplicitConversion(Sema &S, Expr *E, QualType T, | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3508 |                              SourceLocation CC, bool *ICContext = 0) { | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3509 |   if (E->isTypeDependent() || E->isValueDependent()) return; | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3510 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3511 |   const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr(); | 
 | 3512 |   const Type *Target = S.Context.getCanonicalType(T).getTypePtr(); | 
 | 3513 |   if (Source == Target) return; | 
 | 3514 |   if (Target->isDependentType()) return; | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3515 |  | 
| Chandler Carruth | 108f756 | 2011-07-26 05:40:03 +0000 | [diff] [blame] | 3516 |   // If the conversion context location is invalid don't complain. We also | 
 | 3517 |   // don't want to emit a warning if the issue occurs from the expansion of | 
 | 3518 |   // a system macro. The problem is that 'getSpellingLoc()' is slow, so we | 
 | 3519 |   // delay this check as long as possible. Once we detect we are in that | 
 | 3520 |   // scenario, we just return. | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3521 |   if (CC.isInvalid()) | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3522 |     return; | 
 | 3523 |  | 
| Richard Trieu | f1f8b1a | 2011-09-23 20:10:00 +0000 | [diff] [blame] | 3524 |   // Diagnose implicit casts to bool. | 
 | 3525 |   if (Target->isSpecificBuiltinType(BuiltinType::Bool)) { | 
 | 3526 |     if (isa<StringLiteral>(E)) | 
 | 3527 |       // Warn on string literal to bool.  Checks for string literals in logical | 
 | 3528 |       // expressions, for instances, assert(0 && "error here"), is prevented | 
 | 3529 |       // by a check in AnalyzeImplicitConversions(). | 
 | 3530 |       return DiagnoseImpCast(S, E, T, CC, | 
 | 3531 |                              diag::warn_impcast_string_literal_to_bool); | 
| David Blaikie | e37cdc4 | 2011-09-29 04:06:47 +0000 | [diff] [blame] | 3532 |     return; // Other casts to bool are not checked. | 
| Richard Trieu | f1f8b1a | 2011-09-23 20:10:00 +0000 | [diff] [blame] | 3533 |   } | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3534 |  | 
 | 3535 |   // Strip vector types. | 
 | 3536 |   if (isa<VectorType>(Source)) { | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3537 |     if (!isa<VectorType>(Target)) { | 
 | 3538 |       if (isFromSystemMacro(S, CC)) | 
 | 3539 |         return; | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3540 |       return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar); | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3541 |     } | 
| Chris Lattner | b792b30 | 2011-06-14 04:51:15 +0000 | [diff] [blame] | 3542 |      | 
 | 3543 |     // If the vector cast is cast between two vectors of the same size, it is | 
 | 3544 |     // a bitcast, not a conversion. | 
 | 3545 |     if (S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target)) | 
 | 3546 |       return; | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3547 |  | 
 | 3548 |     Source = cast<VectorType>(Source)->getElementType().getTypePtr(); | 
 | 3549 |     Target = cast<VectorType>(Target)->getElementType().getTypePtr(); | 
 | 3550 |   } | 
 | 3551 |  | 
 | 3552 |   // Strip complex types. | 
 | 3553 |   if (isa<ComplexType>(Source)) { | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3554 |     if (!isa<ComplexType>(Target)) { | 
 | 3555 |       if (isFromSystemMacro(S, CC)) | 
 | 3556 |         return; | 
 | 3557 |  | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3558 |       return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar); | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3559 |     } | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3560 |  | 
 | 3561 |     Source = cast<ComplexType>(Source)->getElementType().getTypePtr(); | 
 | 3562 |     Target = cast<ComplexType>(Target)->getElementType().getTypePtr(); | 
 | 3563 |   } | 
 | 3564 |  | 
 | 3565 |   const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source); | 
 | 3566 |   const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target); | 
 | 3567 |  | 
 | 3568 |   // If the source is floating point... | 
 | 3569 |   if (SourceBT && SourceBT->isFloatingPoint()) { | 
 | 3570 |     // ...and the target is floating point... | 
 | 3571 |     if (TargetBT && TargetBT->isFloatingPoint()) { | 
 | 3572 |       // ...then warn if we're dropping FP rank. | 
 | 3573 |  | 
 | 3574 |       // Builtin FP kinds are ordered by increasing FP rank. | 
 | 3575 |       if (SourceBT->getKind() > TargetBT->getKind()) { | 
 | 3576 |         // Don't warn about float constants that are precisely | 
 | 3577 |         // representable in the target type. | 
 | 3578 |         Expr::EvalResult result; | 
| Richard Smith | 51f4708 | 2011-10-29 00:50:52 +0000 | [diff] [blame] | 3579 |         if (E->EvaluateAsRValue(result, S.Context)) { | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3580 |           // Value might be a float, a float vector, or a float complex. | 
 | 3581 |           if (IsSameFloatAfterCast(result.Val, | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3582 |                    S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)), | 
 | 3583 |                    S.Context.getFloatTypeSemantics(QualType(SourceBT, 0)))) | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3584 |             return; | 
 | 3585 |         } | 
 | 3586 |  | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3587 |         if (isFromSystemMacro(S, CC)) | 
 | 3588 |           return; | 
 | 3589 |  | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3590 |         DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision); | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3591 |       } | 
 | 3592 |       return; | 
 | 3593 |     } | 
 | 3594 |  | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3595 |     // If the target is integral, always warn.     | 
| Chandler Carruth | a5b9332 | 2011-02-17 11:05:49 +0000 | [diff] [blame] | 3596 |     if ((TargetBT && TargetBT->isInteger())) { | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3597 |       if (isFromSystemMacro(S, CC)) | 
 | 3598 |         return; | 
 | 3599 |        | 
| Chandler Carruth | a5b9332 | 2011-02-17 11:05:49 +0000 | [diff] [blame] | 3600 |       Expr *InnerE = E->IgnoreParenImpCasts(); | 
| Matt Beaumont-Gay | 634c8af | 2011-09-08 22:30:47 +0000 | [diff] [blame] | 3601 |       // We also want to warn on, e.g., "int i = -1.234" | 
 | 3602 |       if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(InnerE)) | 
 | 3603 |         if (UOp->getOpcode() == UO_Minus || UOp->getOpcode() == UO_Plus) | 
 | 3604 |           InnerE = UOp->getSubExpr()->IgnoreParenImpCasts(); | 
 | 3605 |  | 
| Chandler Carruth | f65076e | 2011-04-10 08:36:24 +0000 | [diff] [blame] | 3606 |       if (FloatingLiteral *FL = dyn_cast<FloatingLiteral>(InnerE)) { | 
 | 3607 |         DiagnoseFloatingLiteralImpCast(S, FL, T, CC); | 
| Chandler Carruth | a5b9332 | 2011-02-17 11:05:49 +0000 | [diff] [blame] | 3608 |       } else { | 
 | 3609 |         DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer); | 
 | 3610 |       } | 
 | 3611 |     } | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3612 |  | 
 | 3613 |     return; | 
 | 3614 |   } | 
 | 3615 |  | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3616 |   if (!Source->isIntegerType() || !Target->isIntegerType()) | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3617 |     return; | 
 | 3618 |  | 
| Richard Trieu | 1838ca5 | 2011-05-29 19:59:02 +0000 | [diff] [blame] | 3619 |   if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) | 
 | 3620 |            == Expr::NPCK_GNUNull) && Target->isIntegerType()) { | 
 | 3621 |     S.Diag(E->getExprLoc(), diag::warn_impcast_null_pointer_to_integer) | 
 | 3622 |         << E->getSourceRange() << clang::SourceRange(CC); | 
 | 3623 |     return; | 
 | 3624 |   } | 
 | 3625 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3626 |   IntRange SourceRange = GetExprRange(S.Context, E); | 
| John McCall | 1844a6e | 2010-11-10 23:38:19 +0000 | [diff] [blame] | 3627 |   IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3628 |  | 
 | 3629 |   if (SourceRange.Width > TargetRange.Width) { | 
| John McCall | 091f23f | 2010-11-09 22:22:12 +0000 | [diff] [blame] | 3630 |     // If the source is a constant, use a default-on diagnostic. | 
 | 3631 |     // TODO: this should happen for bitfield stores, too. | 
 | 3632 |     llvm::APSInt Value(32); | 
 | 3633 |     if (E->isIntegerConstantExpr(Value, S.Context)) { | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3634 |       if (isFromSystemMacro(S, CC)) | 
 | 3635 |         return; | 
 | 3636 |  | 
| John McCall | 091f23f | 2010-11-09 22:22:12 +0000 | [diff] [blame] | 3637 |       std::string PrettySourceValue = Value.toString(10); | 
 | 3638 |       std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); | 
 | 3639 |  | 
| Ted Kremenek | 5e745da | 2011-10-22 02:37:33 +0000 | [diff] [blame] | 3640 |       S.DiagRuntimeBehavior(E->getExprLoc(), E, | 
 | 3641 |         S.PDiag(diag::warn_impcast_integer_precision_constant) | 
 | 3642 |             << PrettySourceValue << PrettyTargetValue | 
 | 3643 |             << E->getType() << T << E->getSourceRange() | 
 | 3644 |             << clang::SourceRange(CC)); | 
| John McCall | 091f23f | 2010-11-09 22:22:12 +0000 | [diff] [blame] | 3645 |       return; | 
 | 3646 |     } | 
 | 3647 |  | 
| Chris Lattner | b792b30 | 2011-06-14 04:51:15 +0000 | [diff] [blame] | 3648 |     // People want to build with -Wshorten-64-to-32 and not -Wconversion. | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3649 |     if (isFromSystemMacro(S, CC)) | 
 | 3650 |       return; | 
 | 3651 |      | 
| John McCall | f2370c9 | 2010-01-06 05:24:50 +0000 | [diff] [blame] | 3652 |     if (SourceRange.Width == 64 && TargetRange.Width == 32) | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3653 |       return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32); | 
 | 3654 |     return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3655 |   } | 
 | 3656 |  | 
 | 3657 |   if ((TargetRange.NonNegative && !SourceRange.NonNegative) || | 
 | 3658 |       (!TargetRange.NonNegative && SourceRange.NonNegative && | 
 | 3659 |        SourceRange.Width == TargetRange.Width)) { | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3660 |          | 
 | 3661 |     if (isFromSystemMacro(S, CC)) | 
 | 3662 |       return; | 
 | 3663 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3664 |     unsigned DiagID = diag::warn_impcast_integer_sign; | 
 | 3665 |  | 
 | 3666 |     // Traditionally, gcc has warned about this under -Wsign-compare. | 
 | 3667 |     // We also want to warn about it in -Wconversion. | 
 | 3668 |     // So if -Wconversion is off, use a completely identical diagnostic | 
 | 3669 |     // in the sign-compare group. | 
 | 3670 |     // The conditional-checking code will  | 
 | 3671 |     if (ICContext) { | 
 | 3672 |       DiagID = diag::warn_impcast_integer_sign_conditional; | 
 | 3673 |       *ICContext = true; | 
 | 3674 |     } | 
 | 3675 |  | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3676 |     return DiagnoseImpCast(S, E, T, CC, DiagID); | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3677 |   } | 
 | 3678 |  | 
| Douglas Gregor | 284cc8d | 2011-02-22 02:45:07 +0000 | [diff] [blame] | 3679 |   // Diagnose conversions between different enumeration types. | 
| Douglas Gregor | 5a5b38f | 2011-03-12 00:14:31 +0000 | [diff] [blame] | 3680 |   // In C, we pretend that the type of an EnumConstantDecl is its enumeration | 
 | 3681 |   // type, to give us better diagnostics. | 
 | 3682 |   QualType SourceType = E->getType(); | 
 | 3683 |   if (!S.getLangOptions().CPlusPlus) { | 
 | 3684 |     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) | 
 | 3685 |       if (EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { | 
 | 3686 |         EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext()); | 
 | 3687 |         SourceType = S.Context.getTypeDeclType(Enum); | 
 | 3688 |         Source = S.Context.getCanonicalType(SourceType).getTypePtr(); | 
 | 3689 |       } | 
 | 3690 |   } | 
 | 3691 |    | 
| Douglas Gregor | 284cc8d | 2011-02-22 02:45:07 +0000 | [diff] [blame] | 3692 |   if (const EnumType *SourceEnum = Source->getAs<EnumType>()) | 
 | 3693 |     if (const EnumType *TargetEnum = Target->getAs<EnumType>()) | 
 | 3694 |       if ((SourceEnum->getDecl()->getIdentifier() ||  | 
| Richard Smith | 162e1c1 | 2011-04-15 14:24:37 +0000 | [diff] [blame] | 3695 |            SourceEnum->getDecl()->getTypedefNameForAnonDecl()) && | 
| Douglas Gregor | 284cc8d | 2011-02-22 02:45:07 +0000 | [diff] [blame] | 3696 |           (TargetEnum->getDecl()->getIdentifier() || | 
| Richard Smith | 162e1c1 | 2011-04-15 14:24:37 +0000 | [diff] [blame] | 3697 |            TargetEnum->getDecl()->getTypedefNameForAnonDecl()) && | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3698 |           SourceEnum != TargetEnum) { | 
 | 3699 |         if (isFromSystemMacro(S, CC)) | 
 | 3700 |           return; | 
 | 3701 |  | 
| Douglas Gregor | 5a5b38f | 2011-03-12 00:14:31 +0000 | [diff] [blame] | 3702 |         return DiagnoseImpCast(S, E, SourceType, T, CC,  | 
| Douglas Gregor | 284cc8d | 2011-02-22 02:45:07 +0000 | [diff] [blame] | 3703 |                                diag::warn_impcast_different_enum_types); | 
| Ted Kremenek | ef9ff88 | 2011-03-10 20:03:42 +0000 | [diff] [blame] | 3704 |       } | 
| Douglas Gregor | 284cc8d | 2011-02-22 02:45:07 +0000 | [diff] [blame] | 3705 |    | 
| John McCall | 51313c3 | 2010-01-04 23:31:57 +0000 | [diff] [blame] | 3706 |   return; | 
 | 3707 | } | 
 | 3708 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3709 | void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T); | 
 | 3710 |  | 
 | 3711 | void CheckConditionalOperand(Sema &S, Expr *E, QualType T, | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3712 |                              SourceLocation CC, bool &ICContext) { | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3713 |   E = E->IgnoreParenImpCasts(); | 
 | 3714 |  | 
 | 3715 |   if (isa<ConditionalOperator>(E)) | 
 | 3716 |     return CheckConditionalOperator(S, cast<ConditionalOperator>(E), T); | 
 | 3717 |  | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3718 |   AnalyzeImplicitConversions(S, E, CC); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3719 |   if (E->getType() != T) | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3720 |     return CheckImplicitConversion(S, E, T, CC, &ICContext); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3721 |   return; | 
 | 3722 | } | 
 | 3723 |  | 
 | 3724 | void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) { | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3725 |   SourceLocation CC = E->getQuestionLoc(); | 
 | 3726 |  | 
 | 3727 |   AnalyzeImplicitConversions(S, E->getCond(), CC); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3728 |  | 
 | 3729 |   bool Suspicious = false; | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3730 |   CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious); | 
 | 3731 |   CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3732 |  | 
 | 3733 |   // If -Wconversion would have warned about either of the candidates | 
 | 3734 |   // for a signedness conversion to the context type... | 
 | 3735 |   if (!Suspicious) return; | 
 | 3736 |  | 
 | 3737 |   // ...but it's currently ignored... | 
| Argyrios Kyrtzidis | 0827408 | 2010-12-15 18:44:22 +0000 | [diff] [blame] | 3738 |   if (S.Diags.getDiagnosticLevel(diag::warn_impcast_integer_sign_conditional, | 
 | 3739 |                                  CC)) | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3740 |     return; | 
 | 3741 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3742 |   // ...then check whether it would have warned about either of the | 
 | 3743 |   // candidates for a signedness conversion to the condition type. | 
| Richard Trieu | 5254161 | 2011-07-21 02:46:28 +0000 | [diff] [blame] | 3744 |   if (E->getType() == T) return; | 
 | 3745 |   | 
 | 3746 |   Suspicious = false; | 
 | 3747 |   CheckImplicitConversion(S, E->getTrueExpr()->IgnoreParenImpCasts(), | 
 | 3748 |                           E->getType(), CC, &Suspicious); | 
 | 3749 |   if (!Suspicious) | 
 | 3750 |     CheckImplicitConversion(S, E->getFalseExpr()->IgnoreParenImpCasts(), | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3751 |                             E->getType(), CC, &Suspicious); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3752 | } | 
 | 3753 |  | 
 | 3754 | /// AnalyzeImplicitConversions - Find and report any interesting | 
 | 3755 | /// implicit conversions in the given expression.  There are a couple | 
 | 3756 | /// of competing diagnostics here, -Wconversion and -Wsign-compare. | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3757 | void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3758 |   QualType T = OrigE->getType(); | 
 | 3759 |   Expr *E = OrigE->IgnoreParenImpCasts(); | 
 | 3760 |  | 
| Douglas Gregor | f8b6e15 | 2011-10-10 17:38:18 +0000 | [diff] [blame] | 3761 |   if (E->isTypeDependent() || E->isValueDependent()) | 
 | 3762 |     return; | 
 | 3763 |  | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3764 |   // For conditional operators, we analyze the arguments as if they | 
 | 3765 |   // were being fed directly into the output. | 
 | 3766 |   if (isa<ConditionalOperator>(E)) { | 
 | 3767 |     ConditionalOperator *CO = cast<ConditionalOperator>(E); | 
 | 3768 |     CheckConditionalOperator(S, CO, T); | 
 | 3769 |     return; | 
 | 3770 |   } | 
 | 3771 |  | 
 | 3772 |   // Go ahead and check any implicit conversions we might have skipped. | 
 | 3773 |   // The non-canonical typecheck is just an optimization; | 
 | 3774 |   // CheckImplicitConversion will filter out dead implicit conversions. | 
 | 3775 |   if (E->getType() != T) | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3776 |     CheckImplicitConversion(S, E, T, CC); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3777 |  | 
 | 3778 |   // Now continue drilling into this expression. | 
 | 3779 |  | 
 | 3780 |   // Skip past explicit casts. | 
 | 3781 |   if (isa<ExplicitCastExpr>(E)) { | 
 | 3782 |     E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts(); | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3783 |     return AnalyzeImplicitConversions(S, E, CC); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3784 |   } | 
 | 3785 |  | 
| John McCall | beb22aa | 2010-11-09 23:24:47 +0000 | [diff] [blame] | 3786 |   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { | 
 | 3787 |     // Do a somewhat different check with comparison operators. | 
 | 3788 |     if (BO->isComparisonOp()) | 
 | 3789 |       return AnalyzeComparison(S, BO); | 
 | 3790 |  | 
 | 3791 |     // And with assignments and compound assignments. | 
 | 3792 |     if (BO->isAssignmentOp()) | 
 | 3793 |       return AnalyzeAssignment(S, BO); | 
 | 3794 |   } | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3795 |  | 
 | 3796 |   // These break the otherwise-useful invariant below.  Fortunately, | 
 | 3797 |   // we don't really need to recurse into them, because any internal | 
 | 3798 |   // expressions should have been analyzed already when they were | 
 | 3799 |   // built into statements. | 
 | 3800 |   if (isa<StmtExpr>(E)) return; | 
 | 3801 |  | 
 | 3802 |   // Don't descend into unevaluated contexts. | 
| Peter Collingbourne | f4e3cfb | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 3803 |   if (isa<UnaryExprOrTypeTraitExpr>(E)) return; | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3804 |  | 
 | 3805 |   // Now just recurse over the expression's children. | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3806 |   CC = E->getExprLoc(); | 
| Richard Trieu | f1f8b1a | 2011-09-23 20:10:00 +0000 | [diff] [blame] | 3807 |   BinaryOperator *BO = dyn_cast<BinaryOperator>(E); | 
 | 3808 |   bool IsLogicalOperator = BO && BO->isLogicalOp(); | 
 | 3809 |   for (Stmt::child_range I = E->children(); I; ++I) { | 
 | 3810 |     Expr *ChildExpr = cast<Expr>(*I); | 
 | 3811 |     if (IsLogicalOperator && | 
 | 3812 |         isa<StringLiteral>(ChildExpr->IgnoreParenImpCasts())) | 
 | 3813 |       // Ignore checking string literals that are in logical operators. | 
 | 3814 |       continue; | 
 | 3815 |     AnalyzeImplicitConversions(S, ChildExpr, CC); | 
 | 3816 |   } | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3817 | } | 
 | 3818 |  | 
 | 3819 | } // end anonymous namespace | 
 | 3820 |  | 
 | 3821 | /// Diagnoses "dangerous" implicit conversions within the given | 
 | 3822 | /// expression (which is a full expression).  Implements -Wconversion | 
 | 3823 | /// and -Wsign-compare. | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3824 | /// | 
 | 3825 | /// \param CC the "context" location of the implicit conversion, i.e. | 
 | 3826 | ///   the most location of the syntactic entity requiring the implicit | 
 | 3827 | ///   conversion | 
 | 3828 | void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) { | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3829 |   // Don't diagnose in unevaluated contexts. | 
 | 3830 |   if (ExprEvalContexts.back().Context == Sema::Unevaluated) | 
 | 3831 |     return; | 
 | 3832 |  | 
 | 3833 |   // Don't diagnose for value- or type-dependent expressions. | 
 | 3834 |   if (E->isTypeDependent() || E->isValueDependent()) | 
 | 3835 |     return; | 
 | 3836 |  | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 3837 |   // Check for array bounds violations in cases where the check isn't triggered | 
 | 3838 |   // elsewhere for other Expr types (like BinaryOperators), e.g. when an | 
 | 3839 |   // ArraySubscriptExpr is on the RHS of a variable initialization. | 
 | 3840 |   CheckArrayAccess(E); | 
 | 3841 |  | 
| John McCall | b4eb64d | 2010-10-08 02:01:28 +0000 | [diff] [blame] | 3842 |   // This is not the right CC for (e.g.) a variable initialization. | 
 | 3843 |   AnalyzeImplicitConversions(*this, E, CC); | 
| John McCall | 323ed74 | 2010-05-06 08:58:33 +0000 | [diff] [blame] | 3844 | } | 
 | 3845 |  | 
| John McCall | 15d7d12 | 2010-11-11 03:21:53 +0000 | [diff] [blame] | 3846 | void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, | 
 | 3847 |                                        FieldDecl *BitField, | 
 | 3848 |                                        Expr *Init) { | 
 | 3849 |   (void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc); | 
 | 3850 | } | 
 | 3851 |  | 
| Mike Stump | f8c4921 | 2010-01-21 03:59:47 +0000 | [diff] [blame] | 3852 | /// CheckParmsForFunctionDef - Check that the parameters of the given | 
 | 3853 | /// function are appropriate for the definition of a function. This | 
 | 3854 | /// takes care of any checks that cannot be performed on the | 
 | 3855 | /// declaration itself, e.g., that the types of each of the function | 
 | 3856 | /// parameters are complete. | 
| Douglas Gregor | 82aa713 | 2010-11-01 18:37:59 +0000 | [diff] [blame] | 3857 | bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd, | 
 | 3858 |                                     bool CheckParameterNames) { | 
| Mike Stump | f8c4921 | 2010-01-21 03:59:47 +0000 | [diff] [blame] | 3859 |   bool HasInvalidParm = false; | 
| Douglas Gregor | 82aa713 | 2010-11-01 18:37:59 +0000 | [diff] [blame] | 3860 |   for (; P != PEnd; ++P) { | 
 | 3861 |     ParmVarDecl *Param = *P; | 
 | 3862 |      | 
| Mike Stump | f8c4921 | 2010-01-21 03:59:47 +0000 | [diff] [blame] | 3863 |     // C99 6.7.5.3p4: the parameters in a parameter type list in a | 
 | 3864 |     // function declarator that is part of a function definition of | 
 | 3865 |     // that function shall not have incomplete type. | 
 | 3866 |     // | 
 | 3867 |     // This is also C++ [dcl.fct]p6. | 
 | 3868 |     if (!Param->isInvalidDecl() && | 
 | 3869 |         RequireCompleteType(Param->getLocation(), Param->getType(), | 
 | 3870 |                                diag::err_typecheck_decl_incomplete_type)) { | 
 | 3871 |       Param->setInvalidDecl(); | 
 | 3872 |       HasInvalidParm = true; | 
 | 3873 |     } | 
 | 3874 |  | 
 | 3875 |     // C99 6.9.1p5: If the declarator includes a parameter type list, the | 
 | 3876 |     // declaration of each parameter shall include an identifier. | 
| Douglas Gregor | 82aa713 | 2010-11-01 18:37:59 +0000 | [diff] [blame] | 3877 |     if (CheckParameterNames && | 
 | 3878 |         Param->getIdentifier() == 0 && | 
| Mike Stump | f8c4921 | 2010-01-21 03:59:47 +0000 | [diff] [blame] | 3879 |         !Param->isImplicit() && | 
 | 3880 |         !getLangOptions().CPlusPlus) | 
 | 3881 |       Diag(Param->getLocation(), diag::err_parameter_name_omitted); | 
| Sam Weinig | d17e340 | 2010-02-01 05:02:49 +0000 | [diff] [blame] | 3882 |  | 
 | 3883 |     // C99 6.7.5.3p12: | 
 | 3884 |     //   If the function declarator is not part of a definition of that | 
 | 3885 |     //   function, parameters may have incomplete type and may use the [*] | 
 | 3886 |     //   notation in their sequences of declarator specifiers to specify | 
 | 3887 |     //   variable length array types. | 
 | 3888 |     QualType PType = Param->getOriginalType(); | 
 | 3889 |     if (const ArrayType *AT = Context.getAsArrayType(PType)) { | 
 | 3890 |       if (AT->getSizeModifier() == ArrayType::Star) { | 
 | 3891 |         // FIXME: This diagnosic should point the the '[*]' if source-location | 
 | 3892 |         // information is added for it. | 
 | 3893 |         Diag(Param->getLocation(), diag::err_array_star_in_function_definition); | 
 | 3894 |       } | 
 | 3895 |     } | 
| Mike Stump | f8c4921 | 2010-01-21 03:59:47 +0000 | [diff] [blame] | 3896 |   } | 
 | 3897 |  | 
 | 3898 |   return HasInvalidParm; | 
 | 3899 | } | 
| John McCall | b7f4ffe | 2010-08-12 21:44:57 +0000 | [diff] [blame] | 3900 |  | 
 | 3901 | /// CheckCastAlign - Implements -Wcast-align, which warns when a | 
 | 3902 | /// pointer cast increases the alignment requirements. | 
 | 3903 | void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { | 
 | 3904 |   // This is actually a lot of work to potentially be doing on every | 
 | 3905 |   // cast; don't do it if we're ignoring -Wcast_align (as is the default). | 
| Argyrios Kyrtzidis | 0827408 | 2010-12-15 18:44:22 +0000 | [diff] [blame] | 3906 |   if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align, | 
 | 3907 |                                           TRange.getBegin()) | 
| David Blaikie | d6471f7 | 2011-09-25 23:23:43 +0000 | [diff] [blame] | 3908 |         == DiagnosticsEngine::Ignored) | 
| John McCall | b7f4ffe | 2010-08-12 21:44:57 +0000 | [diff] [blame] | 3909 |     return; | 
 | 3910 |  | 
 | 3911 |   // Ignore dependent types. | 
 | 3912 |   if (T->isDependentType() || Op->getType()->isDependentType()) | 
 | 3913 |     return; | 
 | 3914 |  | 
 | 3915 |   // Require that the destination be a pointer type. | 
 | 3916 |   const PointerType *DestPtr = T->getAs<PointerType>(); | 
 | 3917 |   if (!DestPtr) return; | 
 | 3918 |  | 
 | 3919 |   // If the destination has alignment 1, we're done. | 
 | 3920 |   QualType DestPointee = DestPtr->getPointeeType(); | 
 | 3921 |   if (DestPointee->isIncompleteType()) return; | 
 | 3922 |   CharUnits DestAlign = Context.getTypeAlignInChars(DestPointee); | 
 | 3923 |   if (DestAlign.isOne()) return; | 
 | 3924 |  | 
 | 3925 |   // Require that the source be a pointer type. | 
 | 3926 |   const PointerType *SrcPtr = Op->getType()->getAs<PointerType>(); | 
 | 3927 |   if (!SrcPtr) return; | 
 | 3928 |   QualType SrcPointee = SrcPtr->getPointeeType(); | 
 | 3929 |  | 
 | 3930 |   // Whitelist casts from cv void*.  We already implicitly | 
 | 3931 |   // whitelisted casts to cv void*, since they have alignment 1. | 
 | 3932 |   // Also whitelist casts involving incomplete types, which implicitly | 
 | 3933 |   // includes 'void'. | 
 | 3934 |   if (SrcPointee->isIncompleteType()) return; | 
 | 3935 |  | 
 | 3936 |   CharUnits SrcAlign = Context.getTypeAlignInChars(SrcPointee); | 
 | 3937 |   if (SrcAlign >= DestAlign) return; | 
 | 3938 |  | 
 | 3939 |   Diag(TRange.getBegin(), diag::warn_cast_align) | 
 | 3940 |     << Op->getType() << T | 
 | 3941 |     << static_cast<unsigned>(SrcAlign.getQuantity()) | 
 | 3942 |     << static_cast<unsigned>(DestAlign.getQuantity()) | 
 | 3943 |     << TRange << Op->getSourceRange(); | 
 | 3944 | } | 
 | 3945 |  | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 3946 | static const Type* getElementType(const Expr *BaseExpr) { | 
 | 3947 |   const Type* EltType = BaseExpr->getType().getTypePtr(); | 
 | 3948 |   if (EltType->isAnyPointerType()) | 
 | 3949 |     return EltType->getPointeeType().getTypePtr(); | 
 | 3950 |   else if (EltType->isArrayType()) | 
 | 3951 |     return EltType->getBaseElementTypeUnsafe(); | 
 | 3952 |   return EltType; | 
 | 3953 | } | 
 | 3954 |  | 
| Chandler Carruth | c268434 | 2011-08-05 09:10:50 +0000 | [diff] [blame] | 3955 | /// \brief Check whether this array fits the idiom of a size-one tail padded | 
 | 3956 | /// array member of a struct. | 
 | 3957 | /// | 
 | 3958 | /// We avoid emitting out-of-bounds access warnings for such arrays as they are | 
 | 3959 | /// commonly used to emulate flexible arrays in C89 code. | 
 | 3960 | static bool IsTailPaddedMemberArray(Sema &S, llvm::APInt Size, | 
 | 3961 |                                     const NamedDecl *ND) { | 
 | 3962 |   if (Size != 1 || !ND) return false; | 
 | 3963 |  | 
 | 3964 |   const FieldDecl *FD = dyn_cast<FieldDecl>(ND); | 
 | 3965 |   if (!FD) return false; | 
 | 3966 |  | 
 | 3967 |   // Don't consider sizes resulting from macro expansions or template argument | 
 | 3968 |   // substitution to form C89 tail-padded arrays. | 
 | 3969 |   ConstantArrayTypeLoc TL = | 
 | 3970 |     cast<ConstantArrayTypeLoc>(FD->getTypeSourceInfo()->getTypeLoc()); | 
 | 3971 |   const Expr *SizeExpr = dyn_cast<IntegerLiteral>(TL.getSizeExpr()); | 
 | 3972 |   if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) | 
 | 3973 |     return false; | 
 | 3974 |  | 
 | 3975 |   const RecordDecl *RD = dyn_cast<RecordDecl>(FD->getDeclContext()); | 
 | 3976 |   if (!RD || !RD->isStruct()) | 
 | 3977 |     return false; | 
 | 3978 |  | 
| Benjamin Kramer | 22d4fed | 2011-08-06 03:04:42 +0000 | [diff] [blame] | 3979 |   // See if this is the last field decl in the record. | 
 | 3980 |   const Decl *D = FD; | 
 | 3981 |   while ((D = D->getNextDeclInContext())) | 
 | 3982 |     if (isa<FieldDecl>(D)) | 
 | 3983 |       return false; | 
 | 3984 |   return true; | 
| Chandler Carruth | c268434 | 2011-08-05 09:10:50 +0000 | [diff] [blame] | 3985 | } | 
 | 3986 |  | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 3987 | void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, | 
 | 3988 |                             bool isSubscript, bool AllowOnePastEnd) { | 
 | 3989 |   const Type* EffectiveType = getElementType(BaseExpr); | 
 | 3990 |   BaseExpr = BaseExpr->IgnoreParenCasts(); | 
 | 3991 |   IndexExpr = IndexExpr->IgnoreParenCasts(); | 
 | 3992 |  | 
| Chandler Carruth | 3406458 | 2011-02-17 20:55:08 +0000 | [diff] [blame] | 3993 |   const ConstantArrayType *ArrayTy = | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 3994 |     Context.getAsConstantArrayType(BaseExpr->getType()); | 
| Chandler Carruth | 3406458 | 2011-02-17 20:55:08 +0000 | [diff] [blame] | 3995 |   if (!ArrayTy) | 
| Ted Kremenek | a0125d8 | 2011-02-16 01:57:07 +0000 | [diff] [blame] | 3996 |     return; | 
| Chandler Carruth | 35001ca | 2011-02-17 21:10:52 +0000 | [diff] [blame] | 3997 |  | 
| Chandler Carruth | 3406458 | 2011-02-17 20:55:08 +0000 | [diff] [blame] | 3998 |   if (IndexExpr->isValueDependent()) | 
| Ted Kremenek | a0125d8 | 2011-02-16 01:57:07 +0000 | [diff] [blame] | 3999 |     return; | 
| Chandler Carruth | 3406458 | 2011-02-17 20:55:08 +0000 | [diff] [blame] | 4000 |   llvm::APSInt index; | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4001 |   if (!IndexExpr->isIntegerConstantExpr(index, Context)) | 
| Ted Kremenek | a0125d8 | 2011-02-16 01:57:07 +0000 | [diff] [blame] | 4002 |     return; | 
| Ted Kremenek | 8fd0a5d | 2011-02-16 04:01:44 +0000 | [diff] [blame] | 4003 |  | 
| Chandler Carruth | ba44712 | 2011-08-05 08:07:29 +0000 | [diff] [blame] | 4004 |   const NamedDecl *ND = NULL; | 
| Chandler Carruth | ba44712 | 2011-08-05 08:07:29 +0000 | [diff] [blame] | 4005 |   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr)) | 
 | 4006 |     ND = dyn_cast<NamedDecl>(DRE->getDecl()); | 
| Chandler Carruth | c268434 | 2011-08-05 09:10:50 +0000 | [diff] [blame] | 4007 |   if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr)) | 
| Chandler Carruth | ba44712 | 2011-08-05 08:07:29 +0000 | [diff] [blame] | 4008 |     ND = dyn_cast<NamedDecl>(ME->getMemberDecl()); | 
| Chandler Carruth | ba44712 | 2011-08-05 08:07:29 +0000 | [diff] [blame] | 4009 |  | 
| Ted Kremenek | 9e060ca | 2011-02-23 23:06:04 +0000 | [diff] [blame] | 4010 |   if (index.isUnsigned() || !index.isNegative()) { | 
| Ted Kremenek | 25b3b84 | 2011-02-18 02:27:00 +0000 | [diff] [blame] | 4011 |     llvm::APInt size = ArrayTy->getSize(); | 
| Chandler Carruth | 35001ca | 2011-02-17 21:10:52 +0000 | [diff] [blame] | 4012 |     if (!size.isStrictlyPositive()) | 
 | 4013 |       return; | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4014 |  | 
 | 4015 |     const Type* BaseType = getElementType(BaseExpr); | 
| Nico Weber | de5998f | 2011-09-17 22:59:41 +0000 | [diff] [blame] | 4016 |     if (BaseType != EffectiveType) { | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4017 |       // Make sure we're comparing apples to apples when comparing index to size | 
 | 4018 |       uint64_t ptrarith_typesize = Context.getTypeSize(EffectiveType); | 
 | 4019 |       uint64_t array_typesize = Context.getTypeSize(BaseType); | 
| Kaelyn Uhrain | d10f4bc | 2011-08-10 19:47:25 +0000 | [diff] [blame] | 4020 |       // Handle ptrarith_typesize being zero, such as when casting to void* | 
| Kaelyn Uhrain | 18f1697 | 2011-08-10 18:49:28 +0000 | [diff] [blame] | 4021 |       if (!ptrarith_typesize) ptrarith_typesize = 1; | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4022 |       if (ptrarith_typesize != array_typesize) { | 
 | 4023 |         // There's a cast to a different size type involved | 
 | 4024 |         uint64_t ratio = array_typesize / ptrarith_typesize; | 
 | 4025 |         // TODO: Be smarter about handling cases where array_typesize is not a | 
 | 4026 |         // multiple of ptrarith_typesize | 
 | 4027 |         if (ptrarith_typesize * ratio == array_typesize) | 
 | 4028 |           size *= llvm::APInt(size.getBitWidth(), ratio); | 
 | 4029 |       } | 
 | 4030 |     } | 
 | 4031 |  | 
| Chandler Carruth | 3406458 | 2011-02-17 20:55:08 +0000 | [diff] [blame] | 4032 |     if (size.getBitWidth() > index.getBitWidth()) | 
 | 4033 |       index = index.sext(size.getBitWidth()); | 
| Ted Kremenek | 25b3b84 | 2011-02-18 02:27:00 +0000 | [diff] [blame] | 4034 |     else if (size.getBitWidth() < index.getBitWidth()) | 
 | 4035 |       size = size.sext(index.getBitWidth()); | 
 | 4036 |  | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4037 |     // For array subscripting the index must be less than size, but for pointer | 
 | 4038 |     // arithmetic also allow the index (offset) to be equal to size since | 
 | 4039 |     // computing the next address after the end of the array is legal and | 
 | 4040 |     // commonly done e.g. in C++ iterators and range-based for loops. | 
 | 4041 |     if (AllowOnePastEnd ? index.sle(size) : index.slt(size)) | 
| Chandler Carruth | ba44712 | 2011-08-05 08:07:29 +0000 | [diff] [blame] | 4042 |       return; | 
 | 4043 |  | 
 | 4044 |     // Also don't warn for arrays of size 1 which are members of some | 
 | 4045 |     // structure. These are often used to approximate flexible arrays in C89 | 
 | 4046 |     // code. | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4047 |     if (IsTailPaddedMemberArray(*this, size, ND)) | 
| Ted Kremenek | 8fd0a5d | 2011-02-16 04:01:44 +0000 | [diff] [blame] | 4048 |       return; | 
| Chandler Carruth | 3406458 | 2011-02-17 20:55:08 +0000 | [diff] [blame] | 4049 |  | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4050 |     unsigned DiagID = diag::warn_ptr_arith_exceeds_bounds; | 
 | 4051 |     if (isSubscript) | 
 | 4052 |       DiagID = diag::warn_array_index_exceeds_bounds; | 
 | 4053 |  | 
 | 4054 |     DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr, | 
 | 4055 |                         PDiag(DiagID) << index.toString(10, true) | 
 | 4056 |                           << size.toString(10, true) | 
 | 4057 |                           << (unsigned)size.getLimitedValue(~0U) | 
 | 4058 |                           << IndexExpr->getSourceRange()); | 
| Chandler Carruth | 3406458 | 2011-02-17 20:55:08 +0000 | [diff] [blame] | 4059 |   } else { | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4060 |     unsigned DiagID = diag::warn_array_index_precedes_bounds; | 
 | 4061 |     if (!isSubscript) { | 
 | 4062 |       DiagID = diag::warn_ptr_arith_precedes_bounds; | 
 | 4063 |       if (index.isNegative()) index = -index; | 
 | 4064 |     } | 
 | 4065 |  | 
 | 4066 |     DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr, | 
 | 4067 |                         PDiag(DiagID) << index.toString(10, true) | 
 | 4068 |                           << IndexExpr->getSourceRange()); | 
| Ted Kremenek | a0125d8 | 2011-02-16 01:57:07 +0000 | [diff] [blame] | 4069 |   } | 
| Chandler Carruth | 35001ca | 2011-02-17 21:10:52 +0000 | [diff] [blame] | 4070 |  | 
| Chandler Carruth | 35001ca | 2011-02-17 21:10:52 +0000 | [diff] [blame] | 4071 |   if (ND) | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4072 |     DiagRuntimeBehavior(ND->getLocStart(), BaseExpr, | 
 | 4073 |                         PDiag(diag::note_array_index_out_of_bounds) | 
 | 4074 |                           << ND->getDeclName()); | 
| Ted Kremenek | a0125d8 | 2011-02-16 01:57:07 +0000 | [diff] [blame] | 4075 | } | 
 | 4076 |  | 
| Ted Kremenek | 3aea4da | 2011-03-01 18:41:00 +0000 | [diff] [blame] | 4077 | void Sema::CheckArrayAccess(const Expr *expr) { | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4078 |   int AllowOnePastEnd = 0; | 
 | 4079 |   while (expr) { | 
 | 4080 |     expr = expr->IgnoreParenImpCasts(); | 
| Ted Kremenek | 3aea4da | 2011-03-01 18:41:00 +0000 | [diff] [blame] | 4081 |     switch (expr->getStmtClass()) { | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4082 |       case Stmt::ArraySubscriptExprClass: { | 
 | 4083 |         const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(expr); | 
 | 4084 |         CheckArrayAccess(ASE->getBase(), ASE->getIdx(), true, | 
 | 4085 |                          AllowOnePastEnd > 0); | 
| Ted Kremenek | 3aea4da | 2011-03-01 18:41:00 +0000 | [diff] [blame] | 4086 |         return; | 
| Kaelyn Uhrain | d6c8865 | 2011-08-05 23:18:04 +0000 | [diff] [blame] | 4087 |       } | 
 | 4088 |       case Stmt::UnaryOperatorClass: { | 
 | 4089 |         // Only unwrap the * and & unary operators | 
 | 4090 |         const UnaryOperator *UO = cast<UnaryOperator>(expr); | 
 | 4091 |         expr = UO->getSubExpr(); | 
 | 4092 |         switch (UO->getOpcode()) { | 
 | 4093 |           case UO_AddrOf: | 
 | 4094 |             AllowOnePastEnd++; | 
 | 4095 |             break; | 
 | 4096 |           case UO_Deref: | 
 | 4097 |             AllowOnePastEnd--; | 
 | 4098 |             break; | 
 | 4099 |           default: | 
 | 4100 |             return; | 
 | 4101 |         } | 
 | 4102 |         break; | 
 | 4103 |       } | 
| Ted Kremenek | 3aea4da | 2011-03-01 18:41:00 +0000 | [diff] [blame] | 4104 |       case Stmt::ConditionalOperatorClass: { | 
 | 4105 |         const ConditionalOperator *cond = cast<ConditionalOperator>(expr); | 
 | 4106 |         if (const Expr *lhs = cond->getLHS()) | 
 | 4107 |           CheckArrayAccess(lhs); | 
 | 4108 |         if (const Expr *rhs = cond->getRHS()) | 
 | 4109 |           CheckArrayAccess(rhs); | 
 | 4110 |         return; | 
 | 4111 |       } | 
 | 4112 |       default: | 
 | 4113 |         return; | 
 | 4114 |     } | 
| Peter Collingbourne | f111d93 | 2011-04-15 00:35:48 +0000 | [diff] [blame] | 4115 |   } | 
| Ted Kremenek | 3aea4da | 2011-03-01 18:41:00 +0000 | [diff] [blame] | 4116 | } | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4117 |  | 
 | 4118 | //===--- CHECK: Objective-C retain cycles ----------------------------------// | 
 | 4119 |  | 
 | 4120 | namespace { | 
 | 4121 |   struct RetainCycleOwner { | 
 | 4122 |     RetainCycleOwner() : Variable(0), Indirect(false) {} | 
 | 4123 |     VarDecl *Variable; | 
 | 4124 |     SourceRange Range; | 
 | 4125 |     SourceLocation Loc; | 
 | 4126 |     bool Indirect; | 
 | 4127 |  | 
 | 4128 |     void setLocsFrom(Expr *e) { | 
 | 4129 |       Loc = e->getExprLoc(); | 
 | 4130 |       Range = e->getSourceRange(); | 
 | 4131 |     } | 
 | 4132 |   }; | 
 | 4133 | } | 
 | 4134 |  | 
 | 4135 | /// Consider whether capturing the given variable can possibly lead to | 
 | 4136 | /// a retain cycle. | 
 | 4137 | static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) { | 
 | 4138 |   // In ARC, it's captured strongly iff the variable has __strong | 
 | 4139 |   // lifetime.  In MRR, it's captured strongly if the variable is | 
 | 4140 |   // __block and has an appropriate type. | 
 | 4141 |   if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong) | 
 | 4142 |     return false; | 
 | 4143 |  | 
 | 4144 |   owner.Variable = var; | 
 | 4145 |   owner.setLocsFrom(ref); | 
 | 4146 |   return true; | 
 | 4147 | } | 
 | 4148 |  | 
 | 4149 | static bool findRetainCycleOwner(Expr *e, RetainCycleOwner &owner) { | 
 | 4150 |   while (true) { | 
 | 4151 |     e = e->IgnoreParens(); | 
 | 4152 |     if (CastExpr *cast = dyn_cast<CastExpr>(e)) { | 
 | 4153 |       switch (cast->getCastKind()) { | 
 | 4154 |       case CK_BitCast: | 
 | 4155 |       case CK_LValueBitCast: | 
 | 4156 |       case CK_LValueToRValue: | 
| John McCall | 33e56f3 | 2011-09-10 06:18:15 +0000 | [diff] [blame] | 4157 |       case CK_ARCReclaimReturnedObject: | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4158 |         e = cast->getSubExpr(); | 
 | 4159 |         continue; | 
 | 4160 |  | 
 | 4161 |       case CK_GetObjCProperty: { | 
 | 4162 |         // Bail out if this isn't a strong explicit property. | 
 | 4163 |         const ObjCPropertyRefExpr *pre = cast->getSubExpr()->getObjCProperty(); | 
 | 4164 |         if (pre->isImplicitProperty()) return false; | 
 | 4165 |         ObjCPropertyDecl *property = pre->getExplicitProperty(); | 
| John McCall | 265941b | 2011-09-13 18:31:23 +0000 | [diff] [blame] | 4166 |         if (!property->isRetaining() && | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4167 |             !(property->getPropertyIvarDecl() && | 
 | 4168 |               property->getPropertyIvarDecl()->getType() | 
 | 4169 |                 .getObjCLifetime() == Qualifiers::OCL_Strong)) | 
 | 4170 |           return false; | 
 | 4171 |  | 
 | 4172 |         owner.Indirect = true; | 
 | 4173 |         e = const_cast<Expr*>(pre->getBase()); | 
 | 4174 |         continue; | 
 | 4175 |       } | 
 | 4176 |          | 
 | 4177 |       default: | 
 | 4178 |         return false; | 
 | 4179 |       } | 
 | 4180 |     } | 
 | 4181 |  | 
 | 4182 |     if (ObjCIvarRefExpr *ref = dyn_cast<ObjCIvarRefExpr>(e)) { | 
 | 4183 |       ObjCIvarDecl *ivar = ref->getDecl(); | 
 | 4184 |       if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong) | 
 | 4185 |         return false; | 
 | 4186 |  | 
 | 4187 |       // Try to find a retain cycle in the base. | 
 | 4188 |       if (!findRetainCycleOwner(ref->getBase(), owner)) | 
 | 4189 |         return false; | 
 | 4190 |  | 
 | 4191 |       if (ref->isFreeIvar()) owner.setLocsFrom(ref); | 
 | 4192 |       owner.Indirect = true; | 
 | 4193 |       return true; | 
 | 4194 |     } | 
 | 4195 |  | 
 | 4196 |     if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) { | 
 | 4197 |       VarDecl *var = dyn_cast<VarDecl>(ref->getDecl()); | 
 | 4198 |       if (!var) return false; | 
 | 4199 |       return considerVariable(var, ref, owner); | 
 | 4200 |     } | 
 | 4201 |  | 
 | 4202 |     if (BlockDeclRefExpr *ref = dyn_cast<BlockDeclRefExpr>(e)) { | 
 | 4203 |       owner.Variable = ref->getDecl(); | 
 | 4204 |       owner.setLocsFrom(ref); | 
 | 4205 |       return true; | 
 | 4206 |     } | 
 | 4207 |  | 
 | 4208 |     if (MemberExpr *member = dyn_cast<MemberExpr>(e)) { | 
 | 4209 |       if (member->isArrow()) return false; | 
 | 4210 |  | 
 | 4211 |       // Don't count this as an indirect ownership. | 
 | 4212 |       e = member->getBase(); | 
 | 4213 |       continue; | 
 | 4214 |     } | 
 | 4215 |  | 
| John McCall | 4b9c2d2 | 2011-11-06 09:01:30 +0000 | [diff] [blame^] | 4216 |     if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) { | 
 | 4217 |       // Only pay attention to pseudo-objects on property references. | 
 | 4218 |       ObjCPropertyRefExpr *pre | 
 | 4219 |         = dyn_cast<ObjCPropertyRefExpr>(pseudo->getSyntacticForm() | 
 | 4220 |                                               ->IgnoreParens()); | 
 | 4221 |       if (!pre) return false; | 
 | 4222 |       if (pre->isImplicitProperty()) return false; | 
 | 4223 |       ObjCPropertyDecl *property = pre->getExplicitProperty(); | 
 | 4224 |       if (!property->isRetaining() && | 
 | 4225 |           !(property->getPropertyIvarDecl() && | 
 | 4226 |             property->getPropertyIvarDecl()->getType() | 
 | 4227 |               .getObjCLifetime() == Qualifiers::OCL_Strong)) | 
 | 4228 |           return false; | 
 | 4229 |  | 
 | 4230 |       owner.Indirect = true; | 
 | 4231 |       e = const_cast<Expr*>(cast<OpaqueValueExpr>(pre->getBase()) | 
 | 4232 |                               ->getSourceExpr()); | 
 | 4233 |       continue; | 
 | 4234 |     } | 
 | 4235 |  | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4236 |     // Array ivars? | 
 | 4237 |  | 
 | 4238 |     return false; | 
 | 4239 |   } | 
 | 4240 | } | 
 | 4241 |  | 
 | 4242 | namespace { | 
 | 4243 |   struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> { | 
 | 4244 |     FindCaptureVisitor(ASTContext &Context, VarDecl *variable) | 
 | 4245 |       : EvaluatedExprVisitor<FindCaptureVisitor>(Context), | 
 | 4246 |         Variable(variable), Capturer(0) {} | 
 | 4247 |  | 
 | 4248 |     VarDecl *Variable; | 
 | 4249 |     Expr *Capturer; | 
 | 4250 |  | 
 | 4251 |     void VisitDeclRefExpr(DeclRefExpr *ref) { | 
 | 4252 |       if (ref->getDecl() == Variable && !Capturer) | 
 | 4253 |         Capturer = ref; | 
 | 4254 |     } | 
 | 4255 |  | 
 | 4256 |     void VisitBlockDeclRefExpr(BlockDeclRefExpr *ref) { | 
 | 4257 |       if (ref->getDecl() == Variable && !Capturer) | 
 | 4258 |         Capturer = ref; | 
 | 4259 |     } | 
 | 4260 |  | 
 | 4261 |     void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) { | 
 | 4262 |       if (Capturer) return; | 
 | 4263 |       Visit(ref->getBase()); | 
 | 4264 |       if (Capturer && ref->isFreeIvar()) | 
 | 4265 |         Capturer = ref; | 
 | 4266 |     } | 
 | 4267 |  | 
 | 4268 |     void VisitBlockExpr(BlockExpr *block) { | 
 | 4269 |       // Look inside nested blocks  | 
 | 4270 |       if (block->getBlockDecl()->capturesVariable(Variable)) | 
 | 4271 |         Visit(block->getBlockDecl()->getBody()); | 
 | 4272 |     } | 
 | 4273 |   }; | 
 | 4274 | } | 
 | 4275 |  | 
 | 4276 | /// Check whether the given argument is a block which captures a | 
 | 4277 | /// variable. | 
 | 4278 | static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) { | 
 | 4279 |   assert(owner.Variable && owner.Loc.isValid()); | 
 | 4280 |  | 
 | 4281 |   e = e->IgnoreParenCasts(); | 
 | 4282 |   BlockExpr *block = dyn_cast<BlockExpr>(e); | 
 | 4283 |   if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable)) | 
 | 4284 |     return 0; | 
 | 4285 |  | 
 | 4286 |   FindCaptureVisitor visitor(S.Context, owner.Variable); | 
 | 4287 |   visitor.Visit(block->getBlockDecl()->getBody()); | 
 | 4288 |   return visitor.Capturer; | 
 | 4289 | } | 
 | 4290 |  | 
 | 4291 | static void diagnoseRetainCycle(Sema &S, Expr *capturer, | 
 | 4292 |                                 RetainCycleOwner &owner) { | 
 | 4293 |   assert(capturer); | 
 | 4294 |   assert(owner.Variable && owner.Loc.isValid()); | 
 | 4295 |  | 
 | 4296 |   S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle) | 
 | 4297 |     << owner.Variable << capturer->getSourceRange(); | 
 | 4298 |   S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner) | 
 | 4299 |     << owner.Indirect << owner.Range; | 
 | 4300 | } | 
 | 4301 |  | 
 | 4302 | /// Check for a keyword selector that starts with the word 'add' or | 
 | 4303 | /// 'set'. | 
 | 4304 | static bool isSetterLikeSelector(Selector sel) { | 
 | 4305 |   if (sel.isUnarySelector()) return false; | 
 | 4306 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 4307 |   StringRef str = sel.getNameForSlot(0); | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4308 |   while (!str.empty() && str.front() == '_') str = str.substr(1); | 
 | 4309 |   if (str.startswith("set") || str.startswith("add")) | 
 | 4310 |     str = str.substr(3); | 
 | 4311 |   else | 
 | 4312 |     return false; | 
 | 4313 |  | 
 | 4314 |   if (str.empty()) return true; | 
 | 4315 |   return !islower(str.front()); | 
 | 4316 | } | 
 | 4317 |  | 
 | 4318 | /// Check a message send to see if it's likely to cause a retain cycle. | 
 | 4319 | void Sema::checkRetainCycles(ObjCMessageExpr *msg) { | 
 | 4320 |   // Only check instance methods whose selector looks like a setter. | 
 | 4321 |   if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector())) | 
 | 4322 |     return; | 
 | 4323 |  | 
 | 4324 |   // Try to find a variable that the receiver is strongly owned by. | 
 | 4325 |   RetainCycleOwner owner; | 
 | 4326 |   if (msg->getReceiverKind() == ObjCMessageExpr::Instance) { | 
 | 4327 |     if (!findRetainCycleOwner(msg->getInstanceReceiver(), owner)) | 
 | 4328 |       return; | 
 | 4329 |   } else { | 
 | 4330 |     assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance); | 
 | 4331 |     owner.Variable = getCurMethodDecl()->getSelfDecl(); | 
 | 4332 |     owner.Loc = msg->getSuperLoc(); | 
 | 4333 |     owner.Range = msg->getSuperLoc(); | 
 | 4334 |   } | 
 | 4335 |  | 
 | 4336 |   // Check whether the receiver is captured by any of the arguments. | 
 | 4337 |   for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i) | 
 | 4338 |     if (Expr *capturer = findCapturingExpr(*this, msg->getArg(i), owner)) | 
 | 4339 |       return diagnoseRetainCycle(*this, capturer, owner); | 
 | 4340 | } | 
 | 4341 |  | 
 | 4342 | /// Check a property assign to see if it's likely to cause a retain cycle. | 
 | 4343 | void Sema::checkRetainCycles(Expr *receiver, Expr *argument) { | 
 | 4344 |   RetainCycleOwner owner; | 
 | 4345 |   if (!findRetainCycleOwner(receiver, owner)) | 
 | 4346 |     return; | 
 | 4347 |  | 
 | 4348 |   if (Expr *capturer = findCapturingExpr(*this, argument, owner)) | 
 | 4349 |     diagnoseRetainCycle(*this, capturer, owner); | 
 | 4350 | } | 
 | 4351 |  | 
| Fariborz Jahanian | 921c143 | 2011-06-24 18:25:34 +0000 | [diff] [blame] | 4352 | bool Sema::checkUnsafeAssigns(SourceLocation Loc, | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4353 |                               QualType LHS, Expr *RHS) { | 
 | 4354 |   Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime(); | 
 | 4355 |   if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone) | 
| Fariborz Jahanian | 921c143 | 2011-06-24 18:25:34 +0000 | [diff] [blame] | 4356 |     return false; | 
 | 4357 |   // strip off any implicit cast added to get to the one arc-specific | 
 | 4358 |   while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) { | 
| John McCall | 33e56f3 | 2011-09-10 06:18:15 +0000 | [diff] [blame] | 4359 |     if (cast->getCastKind() == CK_ARCConsumeObject) { | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4360 |       Diag(Loc, diag::warn_arc_retained_assign) | 
 | 4361 |         << (LT == Qualifiers::OCL_ExplicitNone)  | 
 | 4362 |         << RHS->getSourceRange(); | 
| Fariborz Jahanian | 921c143 | 2011-06-24 18:25:34 +0000 | [diff] [blame] | 4363 |       return true; | 
 | 4364 |     } | 
 | 4365 |     RHS = cast->getSubExpr(); | 
 | 4366 |   } | 
 | 4367 |   return false; | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4368 | } | 
 | 4369 |  | 
| Fariborz Jahanian | 921c143 | 2011-06-24 18:25:34 +0000 | [diff] [blame] | 4370 | void Sema::checkUnsafeExprAssigns(SourceLocation Loc, | 
 | 4371 |                               Expr *LHS, Expr *RHS) { | 
 | 4372 |   QualType LHSType = LHS->getType(); | 
 | 4373 |   if (checkUnsafeAssigns(Loc, LHSType, RHS)) | 
 | 4374 |     return; | 
 | 4375 |   Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime(); | 
 | 4376 |   // FIXME. Check for other life times. | 
 | 4377 |   if (LT != Qualifiers::OCL_None) | 
 | 4378 |     return; | 
 | 4379 |    | 
| John McCall | 3c3b7f9 | 2011-10-25 17:37:35 +0000 | [diff] [blame] | 4380 |   if (ObjCPropertyRefExpr *PRE | 
 | 4381 |         = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens())) { | 
| Fariborz Jahanian | 921c143 | 2011-06-24 18:25:34 +0000 | [diff] [blame] | 4382 |     if (PRE->isImplicitProperty()) | 
 | 4383 |       return; | 
 | 4384 |     const ObjCPropertyDecl *PD = PRE->getExplicitProperty(); | 
 | 4385 |     if (!PD) | 
 | 4386 |       return; | 
 | 4387 |      | 
 | 4388 |     unsigned Attributes = PD->getPropertyAttributes(); | 
 | 4389 |     if (Attributes & ObjCPropertyDecl::OBJC_PR_assign) | 
 | 4390 |       while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) { | 
| John McCall | 33e56f3 | 2011-09-10 06:18:15 +0000 | [diff] [blame] | 4391 |         if (cast->getCastKind() == CK_ARCConsumeObject) { | 
| Fariborz Jahanian | 921c143 | 2011-06-24 18:25:34 +0000 | [diff] [blame] | 4392 |           Diag(Loc, diag::warn_arc_retained_property_assign) | 
 | 4393 |           << RHS->getSourceRange(); | 
 | 4394 |           return; | 
 | 4395 |         } | 
 | 4396 |         RHS = cast->getSubExpr(); | 
 | 4397 |       } | 
 | 4398 |   } | 
 | 4399 | } |