Changeset 56975 in vbox
- Timestamp:
- Jul 18, 2015 12:18:26 AM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 101687
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bldprogs/gccplugin.cpp
r56973 r56975 54 54 55 55 56 /** For use with messages. */ 57 #define MY_LOC(a_hPreferred, a_pState) \ 58 (DECL_P(a_hPreferred) ? DECL_SOURCE_LOCATION(a_hPreferred) : gimple_location((a_pState)->hStmt)) 56 /** For use with messages. 57 * @todo needs some more work... Actually, seems we're a bit handicapped by 58 * working on gimplified stuff. */ 59 #define MY_LOC(a_hPreferred, a_pState) EXPR_LOC_OR_LOC(a_hPreferred, (a_pState)->hFmtLoc) 59 60 60 61 … … 68 69 long iFmt; 69 70 long iArgs; 71 location_t hFmtLoc; 70 72 } MYCHECKSTATE; 71 73 /** Pointer to my checker state. */ … … 202 204 203 205 204 static void MyCheckFormatCString(PMYCHECKSTATE pState, const char *pszFmt, location_t hFmtLoc) 205 { 206 dprintf("checker2: \"%s\"\n", pszFmt); 206 #define MYSTATE_FMT_FILE(a_pState) LOCATION_FILE((a_pState)->hFmtLoc) 207 #define MYSTATE_FMT_LINE(a_pState) LOCATION_LINE((a_pState)->hFmtLoc) 208 #define MYSTATE_FMT_COLUMN(a_pState) LOCATION_COLUMN((a_pState)->hFmtLoc) 209 210 211 /** 212 * Checks that @a iFmtArg isn't present or a valid final dummy argument. 213 * 214 * Will issue warning/error if there are more arguments at @a iFmtArg. 215 * 216 * @param pState The format string checking state. 217 * @param iArg The index of the end of arguments, this is 218 * relative to MYCHECKSTATE::iArgs. 219 */ 220 void MyCheckFinalArg(PMYCHECKSTATE pState, unsigned iArg) 221 { 222 dprintf("MyCheckFinalArg: iArg=%u iArgs=%ld cArgs=%u\n", iArg, pState->iArgs, gimple_call_num_args(pState->hStmt)); 223 if (pState->iArgs > 0) 224 { 225 iArg += pState->iArgs - 1; 226 unsigned cArgs = gimple_call_num_args(pState->hStmt); 227 if (iArg == cArgs) 228 { /* fine */ } 229 else if (iArg < cArgs) 230 { 231 tree hArg = gimple_call_arg(pState->hStmt, iArg); 232 if (cArgs - iArg > 1) 233 warning_at(MY_LOC(hArg, pState), 0, "%u extra arguments not consumed by format string", cArgs - iArg); 234 else if ( TREE_CODE(hArg) != INTEGER_CST 235 || TREE_INT_CST(hArg).fits_shwi() 236 || TREE_INT_CST(hArg).to_shwi() != -99) /* ignore final dummy argument: ..., -99); */ 237 warning_at(MY_LOC(hArg, pState), 0, "one extra argument not consumed by format string"); 238 } 239 /* This should be handled elsewhere, but just in case. */ 240 else if (iArg - 1 == cArgs) 241 warning_at(pState->hFmtLoc, 0, "one argument too few"); 242 else 243 warning_at(pState->hFmtLoc, 0, "%u arguments too few", iArg - cArgs); 244 } 245 } 246 247 248 /** 249 * Does the actual format string checking. 250 * 251 * @todo Move this to different file common to both GCC and CLANG later. 252 * 253 * @param pState The format string checking state. 254 * @param pszFmt The format string. 255 */ 256 void MyCheckFormatCString(PMYCHECKSTATE pState, const char *pszFmt) 257 { 258 dprintf("checker2: \"%s\" at %s:%d col %d\n", pszFmt, 259 MYSTATE_FMT_FILE(pState), MYSTATE_FMT_LINE(pState), MYSTATE_FMT_COLUMN(pState)); 260 unsigned iArg = 0; 261 for (;;) 262 { 263 /* 264 * Skip to the next argument. 265 */ 266 char ch; 267 while ((ch = *pszFmt++) != '%') 268 if (ch == '\0') 269 { 270 MyCheckFinalArg(pState, iArg); 271 return; 272 } 273 274 275 } 207 276 } 208 277 … … 214 283 * passes on to MyCheckFormatString for the actual analyzis. 215 284 * 216 * @param pState The format string check state.285 * @param pState The format string checking state. 217 286 * @param hFmtArg The format string node. 218 287 */ 219 DECL_NO_INLINE(static, void) MyCheckFormat Worker(PMYCHECKSTATE pState, tree hFmtArg)288 DECL_NO_INLINE(static, void) MyCheckFormatNonRecursive(PMYCHECKSTATE pState, tree hFmtArg) 220 289 { 221 290 dprintf("checker: hFmtArg=%p %s\n", hFmtArg, tree_code_name[TREE_CODE(hFmtArg)]); 222 location_t hFmtLoc = MY_LOC(hFmtArg, pState);223 291 224 292 /* … … 236 304 */ 237 305 if (integer_zerop(hFmtArg)) 238 warning_at( hFmtLoc, 0, "Format string should not be NULL");306 warning_at(MY_LOC(hFmtArg, pState), 0, "Format string should not be NULL"); 239 307 /* 240 308 * Need address expression to get any further. … … 244 312 else 245 313 { 246 hFmtLoc = EXPR_LOC_OR_LOC(hFmtArg,hFmtLoc);314 pState->hFmtLoc = EXPR_LOC_OR_LOC(hFmtArg, pState->hFmtLoc); 247 315 hFmtArg = TREE_OPERAND(hFmtArg, 0); 248 316 … … 287 355 dprintf("checker1: Not string literal (%s)\n", tree_code_name[TREE_CODE(hFmtArg)]); 288 356 else if (TYPE_MAIN_VARIANT(TREE_TYPE(TREE_TYPE(hFmtArg))) != char_type_node) 289 warning_at( hFmtLoc, 0, "expected 'char' type string literal");357 warning_at(pState->hFmtLoc, 0, "expected 'char' type string literal"); 290 358 else 291 359 { … … 300 368 { 301 369 if (TREE_CODE(hArraySize) != INTEGER_CST) 302 warning_at( hFmtLoc, 0, "Expected integer array size (not %s)", tree_code_name[TREE_CODE(hArraySize)]);370 warning_at(pState->hFmtLoc, 0, "Expected integer array size (not %s)", tree_code_name[TREE_CODE(hArraySize)]); 303 371 else if (!TREE_INT_CST(hArraySize).fits_shwi()) 304 warning_at( hFmtLoc, 0, "Unexpected integer overflow in array size constant");372 warning_at(pState->hFmtLoc, 0, "Unexpected integer overflow in array size constant"); 305 373 else 306 374 { … … 308 376 if ( cbArray <= 0 309 377 || cbArray != (int)cbArray) 310 warning_at( hFmtLoc, 0, "Unexpected integer array size constant value: %ld", cbArray);378 warning_at(pState->hFmtLoc, 0, "Unexpected integer array size constant value: %ld", cbArray); 311 379 else if (cchFmt > cbArray) 312 380 { … … 334 402 if ( cchFmt < 1 335 403 || pszFmt[cchFmt - 1] != '\0') 336 warning_at( hFmtLoc, 0, "Unterminated format string (cchFmt=%d)", cchFmt);404 warning_at(pState->hFmtLoc, 0, "Unterminated format string (cchFmt=%d)", cchFmt); 337 405 /* 338 406 * Call worker to check the actual string. 339 407 */ 340 408 else 341 MyCheckFormatCString(pState, pszFmt , hFmtLoc);409 MyCheckFormatCString(pState, pszFmt); 342 410 } 343 411 } … … 348 416 * Deal recursively with special format string constructs. 349 417 * 350 * This will call MyCheckFormat Workerto validate each format string.351 * 352 * @param pState The format string check state.418 * This will call MyCheckFormatNonRecursive to validate each format string. 419 * 420 * @param pState The format string checking state. 353 421 * @param hFmtArg The format string node. 354 422 */ … … 378 446 */ 379 447 else 380 MyCheckFormat Worker(pState, hFmtArg);448 MyCheckFormatNonRecursive(pState, hFmtArg); 381 449 } 382 450 … … 443 511 tree const hAttrArgs = TREE_VALUE(hAttr); 444 512 MYCHECKSTATE State; 445 State.iFmt = TREE_INT_CST(TREE_VALUE(hAttrArgs)).to_shwi(); 446 State.iArgs = TREE_INT_CST(TREE_VALUE(TREE_CHAIN(hAttrArgs))).to_shwi(); 447 State.hStmt = hStmt; 513 State.iFmt = TREE_INT_CST(TREE_VALUE(hAttrArgs)).to_shwi(); 514 State.iArgs = TREE_INT_CST(TREE_VALUE(TREE_CHAIN(hAttrArgs))).to_shwi(); 515 State.hStmt = hStmt; 516 State.hFmtLoc = gimple_location(hStmt); 448 517 dprintf(" %s() __iprt_format__(iFmt=%ld, iArgs=%ld)\n", 449 518 DECL_NAME(hFnDecl) ? IDENTIFIER_POINTER(DECL_NAME(hFnDecl)) : "<unamed>", State.iFmt, State.iArgs);
Note:
See TracChangeset
for help on using the changeset viewer.