2007-08-11 04:18:51 +08:00
|
|
|
//===--- SemaChecking.cpp - Extra Semantic Checking -----------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-08-11 04:18:51 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2009-09-09 23:08:12 +08:00
|
|
|
// This file implements extra semantic analysis beyond what is enforced
|
2007-08-11 04:18:51 +08:00
|
|
|
// by the C type system.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Sema.h"
|
2010-01-21 11:59:47 +08:00
|
|
|
#include "clang/Analysis/CFG.h"
|
2010-01-25 12:41:41 +08:00
|
|
|
#include "clang/Analysis/AnalysisContext.h"
|
2010-01-29 07:39:18 +08:00
|
|
|
#include "clang/Analysis/Analyses/PrintfFormatString.h"
|
2007-08-11 04:18:51 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2010-01-12 01:06:35 +08:00
|
|
|
#include "clang/AST/CharUnits.h"
|
2008-08-11 13:35:13 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2007-08-21 00:18:38 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2008-06-17 02:00:42 +08:00
|
|
|
#include "clang/AST/ExprObjC.h"
|
2010-01-21 11:59:47 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
|
|
|
#include "clang/AST/StmtCXX.h"
|
|
|
|
#include "clang/AST/StmtObjC.h"
|
2009-02-19 03:21:10 +08:00
|
|
|
#include "clang/Lex/LiteralSupport.h"
|
2007-08-11 04:18:51 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2010-01-21 11:59:47 +08:00
|
|
|
#include "llvm/ADT/BitVector.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2009-05-20 09:55:10 +08:00
|
|
|
#include <limits>
|
2010-01-21 11:59:47 +08:00
|
|
|
#include <queue>
|
2007-08-11 04:18:51 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2009-02-19 01:49:48 +08:00
|
|
|
/// getLocationOfStringLiteralByte - Return a source location that points to the
|
|
|
|
/// specified byte of the specified string literal.
|
|
|
|
///
|
|
|
|
/// Strings are amazingly complex. They can be formed from multiple tokens and
|
|
|
|
/// can have escape sequences in them in addition to the usual trigraph and
|
|
|
|
/// escaped newline business. This routine handles this complexity.
|
|
|
|
///
|
|
|
|
SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL,
|
|
|
|
unsigned ByteNo) const {
|
|
|
|
assert(!SL->isWide() && "This doesn't work for wide strings yet");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-19 01:49:48 +08:00
|
|
|
// Loop over all of the tokens in this string until we find the one that
|
|
|
|
// contains the byte we're looking for.
|
|
|
|
unsigned TokNo = 0;
|
|
|
|
while (1) {
|
|
|
|
assert(TokNo < SL->getNumConcatenated() && "Invalid byte number!");
|
|
|
|
SourceLocation StrTokLoc = SL->getStrTokenLoc(TokNo);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-19 01:49:48 +08:00
|
|
|
// Get the spelling of the string so that we can get the data that makes up
|
|
|
|
// the string literal, not the identifier for the macro it is potentially
|
|
|
|
// expanded through.
|
|
|
|
SourceLocation StrTokSpellingLoc = SourceMgr.getSpellingLoc(StrTokLoc);
|
|
|
|
|
|
|
|
// Re-lex the token to get its length and original spelling.
|
|
|
|
std::pair<FileID, unsigned> LocInfo =
|
|
|
|
SourceMgr.getDecomposedLoc(StrTokSpellingLoc);
|
|
|
|
std::pair<const char *,const char *> Buffer =
|
|
|
|
SourceMgr.getBufferData(LocInfo.first);
|
|
|
|
const char *StrData = Buffer.first+LocInfo.second;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-19 01:49:48 +08:00
|
|
|
// Create a langops struct and enable trigraphs. This is sufficient for
|
|
|
|
// relexing tokens.
|
|
|
|
LangOptions LangOpts;
|
|
|
|
LangOpts.Trigraphs = true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-19 01:49:48 +08:00
|
|
|
// Create a lexer starting at the beginning of this token.
|
|
|
|
Lexer TheLexer(StrTokSpellingLoc, LangOpts, Buffer.first, StrData,
|
|
|
|
Buffer.second);
|
|
|
|
Token TheTok;
|
|
|
|
TheLexer.LexFromRawLexer(TheTok);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-19 03:26:42 +08:00
|
|
|
// Use the StringLiteralParser to compute the length of the string in bytes.
|
|
|
|
StringLiteralParser SLP(&TheTok, 1, PP);
|
|
|
|
unsigned TokNumBytes = SLP.GetStringLength();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-19 02:52:52 +08:00
|
|
|
// If the byte is in this token, return the location of the byte.
|
2009-02-19 01:49:48 +08:00
|
|
|
if (ByteNo < TokNumBytes ||
|
|
|
|
(ByteNo == TokNumBytes && TokNo == SL->getNumConcatenated())) {
|
2009-09-09 23:08:12 +08:00
|
|
|
unsigned Offset =
|
2009-02-19 03:21:10 +08:00
|
|
|
StringLiteralParser::getOffsetOfStringByte(TheTok, ByteNo, PP);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-19 03:21:10 +08:00
|
|
|
// Now that we know the offset of the token in the spelling, use the
|
|
|
|
// preprocessor to get the offset in the original source.
|
|
|
|
return PP.AdvanceToTokenCharacter(StrTokLoc, Offset);
|
2009-02-19 01:49:48 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-19 01:49:48 +08:00
|
|
|
// Move to the next string token.
|
|
|
|
++TokNo;
|
|
|
|
ByteNo -= TokNumBytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-06 11:00:50 +08:00
|
|
|
/// CheckablePrintfAttr - does a function call have a "printf" attribute
|
|
|
|
/// and arguments that merit checking?
|
|
|
|
bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) {
|
|
|
|
if (Format->getType() == "printf") return true;
|
|
|
|
if (Format->getType() == "printf0") {
|
|
|
|
// printf0 allows null "format" string; if so don't check format/args
|
|
|
|
unsigned format_idx = Format->getFormatIdx() - 1;
|
2009-11-18 02:02:24 +08:00
|
|
|
// Does the index refer to the implicit object argument?
|
|
|
|
if (isa<CXXMemberCallExpr>(TheCall)) {
|
|
|
|
if (format_idx == 0)
|
|
|
|
return false;
|
|
|
|
--format_idx;
|
|
|
|
}
|
2009-08-06 11:00:50 +08:00
|
|
|
if (format_idx < TheCall->getNumArgs()) {
|
|
|
|
Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts();
|
2009-09-25 12:25:58 +08:00
|
|
|
if (!Format->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
|
2009-08-06 11:00:50 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2009-02-19 01:49:48 +08:00
|
|
|
|
2009-01-19 08:08:26 +08:00
|
|
|
Action::OwningExprResult
|
2009-08-16 09:56:34 +08:00
|
|
|
Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
|
2009-01-19 08:08:26 +08:00
|
|
|
OwningExprResult TheCallResult(Owned(TheCall));
|
2008-11-18 04:34:05 +08:00
|
|
|
|
2009-08-16 09:56:34 +08:00
|
|
|
switch (BuiltinID) {
|
2007-12-20 07:59:04 +08:00
|
|
|
case Builtin::BI__builtin___CFStringMakeConstantString:
|
2007-12-28 13:29:59 +08:00
|
|
|
assert(TheCall->getNumArgs() == 1 &&
|
2007-12-20 08:26:33 +08:00
|
|
|
"Wrong # arguments to builtin CFStringMakeConstantString");
|
2009-02-18 14:01:06 +08:00
|
|
|
if (CheckObjCString(TheCall->getArg(0)))
|
2009-01-19 08:08:26 +08:00
|
|
|
return ExprError();
|
2009-08-16 09:56:34 +08:00
|
|
|
break;
|
2008-07-10 01:58:53 +08:00
|
|
|
case Builtin::BI__builtin_stdarg_start:
|
2007-12-20 07:59:04 +08:00
|
|
|
case Builtin::BI__builtin_va_start:
|
2009-01-19 08:08:26 +08:00
|
|
|
if (SemaBuiltinVAStart(TheCall))
|
|
|
|
return ExprError();
|
2009-08-16 09:56:34 +08:00
|
|
|
break;
|
2007-12-20 08:26:33 +08:00
|
|
|
case Builtin::BI__builtin_isgreater:
|
|
|
|
case Builtin::BI__builtin_isgreaterequal:
|
|
|
|
case Builtin::BI__builtin_isless:
|
|
|
|
case Builtin::BI__builtin_islessequal:
|
|
|
|
case Builtin::BI__builtin_islessgreater:
|
|
|
|
case Builtin::BI__builtin_isunordered:
|
2009-01-19 08:08:26 +08:00
|
|
|
if (SemaBuiltinUnorderedCompare(TheCall))
|
|
|
|
return ExprError();
|
2009-08-16 09:56:34 +08:00
|
|
|
break;
|
2009-09-01 04:06:00 +08:00
|
|
|
case Builtin::BI__builtin_isfinite:
|
|
|
|
case Builtin::BI__builtin_isinf:
|
|
|
|
case Builtin::BI__builtin_isinf_sign:
|
|
|
|
case Builtin::BI__builtin_isnan:
|
|
|
|
case Builtin::BI__builtin_isnormal:
|
|
|
|
if (SemaBuiltinUnaryFP(TheCall))
|
|
|
|
return ExprError();
|
|
|
|
break;
|
2008-05-20 16:23:37 +08:00
|
|
|
case Builtin::BI__builtin_return_address:
|
|
|
|
case Builtin::BI__builtin_frame_address:
|
2009-01-19 08:08:26 +08:00
|
|
|
if (SemaBuiltinStackAddress(TheCall))
|
|
|
|
return ExprError();
|
2009-08-16 09:56:34 +08:00
|
|
|
break;
|
2009-09-23 14:06:36 +08:00
|
|
|
case Builtin::BI__builtin_eh_return_data_regno:
|
|
|
|
if (SemaBuiltinEHReturnDataRegNo(TheCall))
|
|
|
|
return ExprError();
|
|
|
|
break;
|
2008-05-15 03:38:39 +08:00
|
|
|
case Builtin::BI__builtin_shufflevector:
|
2009-01-19 08:08:26 +08:00
|
|
|
return SemaBuiltinShuffleVector(TheCall);
|
|
|
|
// TheCall will be freed by the smart pointer here, but that's fine, since
|
|
|
|
// SemaBuiltinShuffleVector guts it, but then doesn't release it.
|
2008-07-22 06:59:13 +08:00
|
|
|
case Builtin::BI__builtin_prefetch:
|
2009-01-19 08:08:26 +08:00
|
|
|
if (SemaBuiltinPrefetch(TheCall))
|
|
|
|
return ExprError();
|
2009-08-16 09:56:34 +08:00
|
|
|
break;
|
2008-09-04 05:13:56 +08:00
|
|
|
case Builtin::BI__builtin_object_size:
|
2009-01-19 08:08:26 +08:00
|
|
|
if (SemaBuiltinObjectSize(TheCall))
|
|
|
|
return ExprError();
|
2009-08-16 09:56:34 +08:00
|
|
|
break;
|
2009-05-03 12:46:36 +08:00
|
|
|
case Builtin::BI__builtin_longjmp:
|
|
|
|
if (SemaBuiltinLongjmp(TheCall))
|
|
|
|
return ExprError();
|
2009-08-16 09:56:34 +08:00
|
|
|
break;
|
2009-05-08 14:58:22 +08:00
|
|
|
case Builtin::BI__sync_fetch_and_add:
|
|
|
|
case Builtin::BI__sync_fetch_and_sub:
|
|
|
|
case Builtin::BI__sync_fetch_and_or:
|
|
|
|
case Builtin::BI__sync_fetch_and_and:
|
|
|
|
case Builtin::BI__sync_fetch_and_xor:
|
2009-05-13 12:37:52 +08:00
|
|
|
case Builtin::BI__sync_fetch_and_nand:
|
2009-05-08 14:58:22 +08:00
|
|
|
case Builtin::BI__sync_add_and_fetch:
|
|
|
|
case Builtin::BI__sync_sub_and_fetch:
|
|
|
|
case Builtin::BI__sync_and_and_fetch:
|
|
|
|
case Builtin::BI__sync_or_and_fetch:
|
|
|
|
case Builtin::BI__sync_xor_and_fetch:
|
2009-05-13 12:37:52 +08:00
|
|
|
case Builtin::BI__sync_nand_and_fetch:
|
2009-05-08 14:58:22 +08:00
|
|
|
case Builtin::BI__sync_val_compare_and_swap:
|
|
|
|
case Builtin::BI__sync_bool_compare_and_swap:
|
|
|
|
case Builtin::BI__sync_lock_test_and_set:
|
|
|
|
case Builtin::BI__sync_lock_release:
|
|
|
|
if (SemaBuiltinAtomicOverloaded(TheCall))
|
|
|
|
return ExprError();
|
2009-08-16 09:56:34 +08:00
|
|
|
break;
|
2007-08-17 13:31:46 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-16 09:56:34 +08:00
|
|
|
return move(TheCallResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// CheckFunctionCall - Check a direct function call for various correctness
|
|
|
|
/// and safety properties not strictly enforced by the C type system.
|
|
|
|
bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
|
|
|
|
// Get the IdentifierInfo* for the called function.
|
|
|
|
IdentifierInfo *FnInfo = FDecl->getIdentifier();
|
2008-10-03 02:44:07 +08:00
|
|
|
|
2009-08-16 09:56:34 +08:00
|
|
|
// None of the checks below are needed for functions that don't have
|
|
|
|
// simple names (e.g., C++ conversion functions).
|
|
|
|
if (!FnInfo)
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-10-03 02:44:07 +08:00
|
|
|
// FIXME: This mechanism should be abstracted to be less fragile and
|
|
|
|
// more efficient. For example, just map function ids to custom
|
|
|
|
// handlers.
|
|
|
|
|
2007-08-11 04:18:51 +08:00
|
|
|
// Printf checking.
|
2009-06-30 10:34:44 +08:00
|
|
|
if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>()) {
|
2009-08-06 11:00:50 +08:00
|
|
|
if (CheckablePrintfAttr(Format, TheCall)) {
|
2009-02-28 01:58:43 +08:00
|
|
|
bool HasVAListArg = Format->getFirstArg() == 0;
|
|
|
|
if (!HasVAListArg) {
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const FunctionProtoType *Proto
|
2009-09-22 07:43:11 +08:00
|
|
|
= FDecl->getType()->getAs<FunctionProtoType>())
|
2009-11-18 02:02:24 +08:00
|
|
|
HasVAListArg = !Proto->isVariadic();
|
2009-02-28 01:58:43 +08:00
|
|
|
}
|
2009-02-15 02:57:46 +08:00
|
|
|
CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
|
2009-02-28 01:58:43 +08:00
|
|
|
HasVAListArg ? 0 : Format->getFirstArg() - 1);
|
2009-02-15 02:57:46 +08:00
|
|
|
}
|
2007-08-11 04:18:51 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
for (const NonNullAttr *NonNull = FDecl->getAttr<NonNullAttr>(); NonNull;
|
2009-08-16 09:56:34 +08:00
|
|
|
NonNull = NonNull->getNext<NonNullAttr>())
|
|
|
|
CheckNonNullArguments(NonNull, TheCall);
|
2009-01-19 08:08:26 +08:00
|
|
|
|
2009-08-16 09:56:34 +08:00
|
|
|
return false;
|
2007-08-17 13:31:46 +08:00
|
|
|
}
|
|
|
|
|
2009-08-16 09:56:34 +08:00
|
|
|
bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
|
2009-05-19 05:05:18 +08:00
|
|
|
// Printf checking.
|
2009-06-30 10:34:44 +08:00
|
|
|
const FormatAttr *Format = NDecl->getAttr<FormatAttr>();
|
2009-05-19 05:05:18 +08:00
|
|
|
if (!Format)
|
2009-08-16 09:56:34 +08:00
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-19 05:05:18 +08:00
|
|
|
const VarDecl *V = dyn_cast<VarDecl>(NDecl);
|
|
|
|
if (!V)
|
2009-08-16 09:56:34 +08:00
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-19 05:05:18 +08:00
|
|
|
QualType Ty = V->getType();
|
|
|
|
if (!Ty->isBlockPointerType())
|
2009-08-16 09:56:34 +08:00
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-16 09:56:34 +08:00
|
|
|
if (!CheckablePrintfAttr(Format, TheCall))
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-16 09:56:34 +08:00
|
|
|
bool HasVAListArg = Format->getFirstArg() == 0;
|
|
|
|
if (!HasVAListArg) {
|
2009-09-09 23:08:12 +08:00
|
|
|
const FunctionType *FT =
|
2009-09-22 07:43:11 +08:00
|
|
|
Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
|
2009-08-16 09:56:34 +08:00
|
|
|
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
|
|
|
|
HasVAListArg = !Proto->isVariadic();
|
2009-05-19 05:05:18 +08:00
|
|
|
}
|
2009-08-16 09:56:34 +08:00
|
|
|
CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
|
|
|
|
HasVAListArg ? 0 : Format->getFirstArg() - 1);
|
|
|
|
|
|
|
|
return false;
|
2009-05-19 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
/// SemaBuiltinAtomicOverloaded - We have a call to a function like
|
|
|
|
/// __sync_fetch_and_add, which is an overloaded function based on the pointer
|
|
|
|
/// type of its first argument. The main ActOnCallExpr routines have already
|
|
|
|
/// promoted the types of arguments because all of these calls are prototyped as
|
|
|
|
/// void(...).
|
|
|
|
///
|
|
|
|
/// This function goes through and does final semantic checking for these
|
|
|
|
/// builtins,
|
|
|
|
bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
|
|
|
|
DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
|
|
|
|
FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
|
|
|
|
|
|
|
|
// Ensure that we have at least one argument to do type inference from.
|
|
|
|
if (TheCall->getNumArgs() < 1)
|
|
|
|
return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
|
|
|
|
<< 0 << TheCall->getCallee()->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
// Inspect the first argument of the atomic builtin. This should always be
|
|
|
|
// a pointer type, whose element is an integral scalar or pointer type.
|
|
|
|
// Because it is a pointer type, we don't have to worry about any implicit
|
|
|
|
// casts here.
|
|
|
|
Expr *FirstArg = TheCall->getArg(0);
|
|
|
|
if (!FirstArg->getType()->isPointerType())
|
|
|
|
return Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
|
|
|
|
<< FirstArg->getType() << FirstArg->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
QualType ValType = FirstArg->getType()->getAs<PointerType>()->getPointeeType();
|
2009-09-09 23:08:12 +08:00
|
|
|
if (!ValType->isIntegerType() && !ValType->isPointerType() &&
|
2009-05-08 14:58:22 +08:00
|
|
|
!ValType->isBlockPointerType())
|
|
|
|
return Diag(DRE->getLocStart(),
|
|
|
|
diag::err_atomic_builtin_must_be_pointer_intptr)
|
|
|
|
<< FirstArg->getType() << FirstArg->getSourceRange();
|
|
|
|
|
|
|
|
// We need to figure out which concrete builtin this maps onto. For example,
|
|
|
|
// __sync_fetch_and_add with a 2 byte object turns into
|
|
|
|
// __sync_fetch_and_add_2.
|
|
|
|
#define BUILTIN_ROW(x) \
|
|
|
|
{ Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \
|
|
|
|
Builtin::BI##x##_8, Builtin::BI##x##_16 }
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
static const unsigned BuiltinIndices[][5] = {
|
|
|
|
BUILTIN_ROW(__sync_fetch_and_add),
|
|
|
|
BUILTIN_ROW(__sync_fetch_and_sub),
|
|
|
|
BUILTIN_ROW(__sync_fetch_and_or),
|
|
|
|
BUILTIN_ROW(__sync_fetch_and_and),
|
|
|
|
BUILTIN_ROW(__sync_fetch_and_xor),
|
2009-05-13 12:37:52 +08:00
|
|
|
BUILTIN_ROW(__sync_fetch_and_nand),
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
BUILTIN_ROW(__sync_add_and_fetch),
|
|
|
|
BUILTIN_ROW(__sync_sub_and_fetch),
|
|
|
|
BUILTIN_ROW(__sync_and_and_fetch),
|
|
|
|
BUILTIN_ROW(__sync_or_and_fetch),
|
|
|
|
BUILTIN_ROW(__sync_xor_and_fetch),
|
2009-05-13 12:37:52 +08:00
|
|
|
BUILTIN_ROW(__sync_nand_and_fetch),
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
BUILTIN_ROW(__sync_val_compare_and_swap),
|
|
|
|
BUILTIN_ROW(__sync_bool_compare_and_swap),
|
|
|
|
BUILTIN_ROW(__sync_lock_test_and_set),
|
|
|
|
BUILTIN_ROW(__sync_lock_release)
|
|
|
|
};
|
2009-09-09 23:08:12 +08:00
|
|
|
#undef BUILTIN_ROW
|
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
// Determine the index of the size.
|
|
|
|
unsigned SizeIndex;
|
2010-01-12 01:06:35 +08:00
|
|
|
switch (Context.getTypeSizeInChars(ValType).getQuantity()) {
|
2009-05-08 14:58:22 +08:00
|
|
|
case 1: SizeIndex = 0; break;
|
|
|
|
case 2: SizeIndex = 1; break;
|
|
|
|
case 4: SizeIndex = 2; break;
|
|
|
|
case 8: SizeIndex = 3; break;
|
|
|
|
case 16: SizeIndex = 4; break;
|
|
|
|
default:
|
|
|
|
return Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size)
|
|
|
|
<< FirstArg->getType() << FirstArg->getSourceRange();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
// Each of these builtins has one pointer argument, followed by some number of
|
|
|
|
// values (0, 1 or 2) followed by a potentially empty varags list of stuff
|
|
|
|
// that we ignore. Find out which row of BuiltinIndices to read from as well
|
|
|
|
// as the number of fixed args.
|
2009-09-12 08:22:50 +08:00
|
|
|
unsigned BuiltinID = FDecl->getBuiltinID();
|
2009-05-08 14:58:22 +08:00
|
|
|
unsigned BuiltinIndex, NumFixed = 1;
|
|
|
|
switch (BuiltinID) {
|
|
|
|
default: assert(0 && "Unknown overloaded atomic builtin!");
|
|
|
|
case Builtin::BI__sync_fetch_and_add: BuiltinIndex = 0; break;
|
|
|
|
case Builtin::BI__sync_fetch_and_sub: BuiltinIndex = 1; break;
|
|
|
|
case Builtin::BI__sync_fetch_and_or: BuiltinIndex = 2; break;
|
|
|
|
case Builtin::BI__sync_fetch_and_and: BuiltinIndex = 3; break;
|
|
|
|
case Builtin::BI__sync_fetch_and_xor: BuiltinIndex = 4; break;
|
2009-05-13 12:37:52 +08:00
|
|
|
case Builtin::BI__sync_fetch_and_nand:BuiltinIndex = 5; break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-13 12:37:52 +08:00
|
|
|
case Builtin::BI__sync_add_and_fetch: BuiltinIndex = 6; break;
|
|
|
|
case Builtin::BI__sync_sub_and_fetch: BuiltinIndex = 7; break;
|
|
|
|
case Builtin::BI__sync_and_and_fetch: BuiltinIndex = 8; break;
|
|
|
|
case Builtin::BI__sync_or_and_fetch: BuiltinIndex = 9; break;
|
|
|
|
case Builtin::BI__sync_xor_and_fetch: BuiltinIndex =10; break;
|
|
|
|
case Builtin::BI__sync_nand_and_fetch:BuiltinIndex =11; break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
case Builtin::BI__sync_val_compare_and_swap:
|
2009-05-13 12:37:52 +08:00
|
|
|
BuiltinIndex = 12;
|
2009-05-08 14:58:22 +08:00
|
|
|
NumFixed = 2;
|
|
|
|
break;
|
|
|
|
case Builtin::BI__sync_bool_compare_and_swap:
|
2009-05-13 12:37:52 +08:00
|
|
|
BuiltinIndex = 13;
|
2009-05-08 14:58:22 +08:00
|
|
|
NumFixed = 2;
|
|
|
|
break;
|
2009-05-13 12:37:52 +08:00
|
|
|
case Builtin::BI__sync_lock_test_and_set: BuiltinIndex = 14; break;
|
2009-05-08 14:58:22 +08:00
|
|
|
case Builtin::BI__sync_lock_release:
|
2009-05-13 12:37:52 +08:00
|
|
|
BuiltinIndex = 15;
|
2009-05-08 14:58:22 +08:00
|
|
|
NumFixed = 0;
|
|
|
|
break;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
// Now that we know how many fixed arguments we expect, first check that we
|
|
|
|
// have at least that many.
|
|
|
|
if (TheCall->getNumArgs() < 1+NumFixed)
|
|
|
|
return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
|
|
|
|
<< 0 << TheCall->getCallee()->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
2009-05-08 23:36:58 +08:00
|
|
|
// Get the decl for the concrete builtin from this, we can tell what the
|
|
|
|
// concrete integer type we should convert to is.
|
|
|
|
unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
|
|
|
|
const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID);
|
|
|
|
IdentifierInfo *NewBuiltinII = PP.getIdentifierInfo(NewBuiltinName);
|
2009-09-09 23:08:12 +08:00
|
|
|
FunctionDecl *NewBuiltinDecl =
|
2009-05-08 23:36:58 +08:00
|
|
|
cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID,
|
|
|
|
TUScope, false, DRE->getLocStart()));
|
|
|
|
const FunctionProtoType *BuiltinFT =
|
2009-09-22 07:43:11 +08:00
|
|
|
NewBuiltinDecl->getType()->getAs<FunctionProtoType>();
|
2009-07-30 05:53:49 +08:00
|
|
|
ValType = BuiltinFT->getArgType(0)->getAs<PointerType>()->getPointeeType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 23:36:58 +08:00
|
|
|
// If the first type needs to be converted (e.g. void** -> int*), do it now.
|
|
|
|
if (BuiltinFT->getArgType(0) != FirstArg->getType()) {
|
2009-10-20 16:27:19 +08:00
|
|
|
ImpCastExprToType(FirstArg, BuiltinFT->getArgType(0), CastExpr::CK_BitCast);
|
2009-05-08 23:36:58 +08:00
|
|
|
TheCall->setArg(0, FirstArg);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
// Next, walk the valid ones promoting to the right type.
|
|
|
|
for (unsigned i = 0; i != NumFixed; ++i) {
|
|
|
|
Expr *Arg = TheCall->getArg(i+1);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
// If the argument is an implicit cast, then there was a promotion due to
|
|
|
|
// "...", just remove it now.
|
|
|
|
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
|
|
|
|
Arg = ICE->getSubExpr();
|
|
|
|
ICE->setSubExpr(0);
|
|
|
|
ICE->Destroy(Context);
|
|
|
|
TheCall->setArg(i+1, Arg);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
// GCC does an implicit conversion to the pointer or integer ValType. This
|
|
|
|
// can fail in some cases (1i -> int**), check for this error case now.
|
2009-08-08 06:21:05 +08:00
|
|
|
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
|
2009-08-27 02:55:36 +08:00
|
|
|
CXXMethodDecl *ConversionDecl = 0;
|
|
|
|
if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind,
|
|
|
|
ConversionDecl))
|
2009-05-08 14:58:22 +08:00
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
// Okay, we have something that *can* be converted to the right type. Check
|
|
|
|
// to see if there is a potentially weird extension going on here. This can
|
|
|
|
// happen when you do an atomic operation on something like an char* and
|
|
|
|
// pass in 42. The 42 gets converted to char. This is even more strange
|
|
|
|
// for things like 45.123 -> char, etc.
|
2009-09-09 23:08:12 +08:00
|
|
|
// FIXME: Do this check.
|
2009-08-08 06:21:05 +08:00
|
|
|
ImpCastExprToType(Arg, ValType, Kind, /*isLvalue=*/false);
|
2009-05-08 14:58:22 +08:00
|
|
|
TheCall->setArg(i+1, Arg);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
// Switch the DeclRefExpr to refer to the new decl.
|
|
|
|
DRE->setDecl(NewBuiltinDecl);
|
|
|
|
DRE->setType(NewBuiltinDecl->getType());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
// Set the callee in the CallExpr.
|
|
|
|
// FIXME: This leaks the original parens and implicit casts.
|
|
|
|
Expr *PromotedCall = DRE;
|
|
|
|
UsualUnaryConversions(PromotedCall);
|
|
|
|
TheCall->setCallee(PromotedCall);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-08 14:58:22 +08:00
|
|
|
|
|
|
|
// Change the result type of the call to match the result type of the decl.
|
|
|
|
TheCall->setType(NewBuiltinDecl->getResultType());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-18 14:01:06 +08:00
|
|
|
/// CheckObjCString - Checks that the argument to the builtin
|
2007-08-17 13:31:46 +08:00
|
|
|
/// CFString constructor is correct
|
2009-04-14 04:26:29 +08:00
|
|
|
/// FIXME: GCC currently emits the following warning:
|
2009-09-09 23:08:12 +08:00
|
|
|
/// "warning: input conversion stopped due to an input byte that does not
|
2009-04-14 04:26:29 +08:00
|
|
|
/// belong to the input codeset UTF-8"
|
|
|
|
/// Note: It might also make sense to do the UTF-16 conversion here (would
|
|
|
|
/// simplify the backend).
|
2009-02-18 14:01:06 +08:00
|
|
|
bool Sema::CheckObjCString(Expr *Arg) {
|
2008-02-13 09:02:39 +08:00
|
|
|
Arg = Arg->IgnoreParenCasts();
|
2007-08-17 13:31:46 +08:00
|
|
|
StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);
|
|
|
|
|
|
|
|
if (!Literal || Literal->isWide()) {
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(Arg->getLocStart(), diag::err_cfstring_literal_not_string_constant)
|
|
|
|
<< Arg->getSourceRange();
|
2007-08-17 23:44:17 +08:00
|
|
|
return true;
|
2007-08-17 13:31:46 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-22 18:03:52 +08:00
|
|
|
const char *Data = Literal->getStrData();
|
|
|
|
unsigned Length = Literal->getByteLength();
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < Length; ++i) {
|
|
|
|
if (!Data[i]) {
|
|
|
|
Diag(getLocationOfStringLiteralByte(Literal, i),
|
|
|
|
diag::warn_cfstring_literal_contains_nul_character)
|
|
|
|
<< Arg->getSourceRange();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-17 23:44:17 +08:00
|
|
|
return false;
|
2007-08-11 04:18:51 +08:00
|
|
|
}
|
|
|
|
|
2007-12-20 08:05:45 +08:00
|
|
|
/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity.
|
|
|
|
/// Emit an error and return true on failure, return false on success.
|
2007-12-28 13:29:59 +08:00
|
|
|
bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
|
|
|
|
Expr *Fn = TheCall->getCallee();
|
|
|
|
if (TheCall->getNumArgs() > 2) {
|
2008-11-22 02:44:24 +08:00
|
|
|
Diag(TheCall->getArg(2)->getLocStart(),
|
2008-11-19 13:08:23 +08:00
|
|
|
diag::err_typecheck_call_too_many_args)
|
2008-11-22 02:44:24 +08:00
|
|
|
<< 0 /*function call*/ << Fn->getSourceRange()
|
2009-09-09 23:08:12 +08:00
|
|
|
<< SourceRange(TheCall->getArg(2)->getLocStart(),
|
2008-11-19 13:08:23 +08:00
|
|
|
(*(TheCall->arg_end()-1))->getLocEnd());
|
2007-12-20 07:59:04 +08:00
|
|
|
return true;
|
|
|
|
}
|
2008-12-16 06:05:35 +08:00
|
|
|
|
|
|
|
if (TheCall->getNumArgs() < 2) {
|
|
|
|
return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
|
|
|
|
<< 0 /*function call*/;
|
|
|
|
}
|
|
|
|
|
2007-12-20 08:05:45 +08:00
|
|
|
// Determine whether the current function is variadic or not.
|
|
|
|
bool isVariadic;
|
2009-04-16 03:33:47 +08:00
|
|
|
if (CurBlock)
|
|
|
|
isVariadic = CurBlock->isVariadic;
|
|
|
|
else if (getCurFunctionDecl()) {
|
2009-02-27 07:50:07 +08:00
|
|
|
if (FunctionProtoType* FTP =
|
|
|
|
dyn_cast<FunctionProtoType>(getCurFunctionDecl()->getType()))
|
2008-12-16 06:05:35 +08:00
|
|
|
isVariadic = FTP->isVariadic();
|
|
|
|
else
|
|
|
|
isVariadic = false;
|
|
|
|
} else {
|
2008-06-28 14:07:14 +08:00
|
|
|
isVariadic = getCurMethodDecl()->isVariadic();
|
2008-12-16 06:05:35 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-20 08:05:45 +08:00
|
|
|
if (!isVariadic) {
|
2007-12-20 07:59:04 +08:00
|
|
|
Diag(Fn->getLocStart(), diag::err_va_start_used_in_non_variadic_function);
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-20 07:59:04 +08:00
|
|
|
// Verify that the second argument to the builtin is the last argument of the
|
|
|
|
// current function or method.
|
|
|
|
bool SecondArgIsLastNamedArgument = false;
|
2008-02-13 09:22:59 +08:00
|
|
|
const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-02-11 12:20:54 +08:00
|
|
|
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
|
|
|
|
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
|
2007-12-20 07:59:04 +08:00
|
|
|
// FIXME: This isn't correct for methods (results in bogus warning).
|
|
|
|
// Get the last formal in the current function.
|
2008-02-11 12:20:54 +08:00
|
|
|
const ParmVarDecl *LastArg;
|
2009-04-16 03:33:47 +08:00
|
|
|
if (CurBlock)
|
|
|
|
LastArg = *(CurBlock->TheDecl->param_end()-1);
|
|
|
|
else if (FunctionDecl *FD = getCurFunctionDecl())
|
2008-12-05 07:50:19 +08:00
|
|
|
LastArg = *(FD->param_end()-1);
|
2007-12-20 07:59:04 +08:00
|
|
|
else
|
2008-06-28 14:07:14 +08:00
|
|
|
LastArg = *(getCurMethodDecl()->param_end()-1);
|
2007-12-20 07:59:04 +08:00
|
|
|
SecondArgIsLastNamedArgument = PV == LastArg;
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-20 07:59:04 +08:00
|
|
|
if (!SecondArgIsLastNamedArgument)
|
2009-09-09 23:08:12 +08:00
|
|
|
Diag(TheCall->getArg(1)->getLocStart(),
|
2007-12-20 07:59:04 +08:00
|
|
|
diag::warn_second_parameter_of_va_start_not_last_named_argument);
|
|
|
|
return false;
|
2008-05-20 16:23:37 +08:00
|
|
|
}
|
2007-12-20 07:59:04 +08:00
|
|
|
|
2007-12-20 08:26:33 +08:00
|
|
|
/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and
|
|
|
|
/// friends. This is declared to take (...), so we have to check everything.
|
2007-12-28 13:29:59 +08:00
|
|
|
bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
|
|
|
|
if (TheCall->getNumArgs() < 2)
|
2008-11-22 02:44:24 +08:00
|
|
|
return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
|
|
|
|
<< 0 /*function call*/;
|
2007-12-28 13:29:59 +08:00
|
|
|
if (TheCall->getNumArgs() > 2)
|
2009-09-09 23:08:12 +08:00
|
|
|
return Diag(TheCall->getArg(2)->getLocStart(),
|
2008-11-19 13:08:23 +08:00
|
|
|
diag::err_typecheck_call_too_many_args)
|
2008-11-22 02:44:24 +08:00
|
|
|
<< 0 /*function call*/
|
2008-11-19 13:08:23 +08:00
|
|
|
<< SourceRange(TheCall->getArg(2)->getLocStart(),
|
|
|
|
(*(TheCall->arg_end()-1))->getLocEnd());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:29:59 +08:00
|
|
|
Expr *OrigArg0 = TheCall->getArg(0);
|
|
|
|
Expr *OrigArg1 = TheCall->getArg(1);
|
2009-05-20 06:10:17 +08:00
|
|
|
|
2007-12-20 08:26:33 +08:00
|
|
|
// Do standard promotions between the two arguments, returning their common
|
|
|
|
// type.
|
2007-12-28 13:29:59 +08:00
|
|
|
QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false);
|
2009-02-20 03:28:43 +08:00
|
|
|
|
|
|
|
// Make sure any conversions are pushed back into the call; this is
|
|
|
|
// type safe since unordered compare builtins are declared as "_Bool
|
|
|
|
// foo(...)".
|
|
|
|
TheCall->setArg(0, OrigArg0);
|
|
|
|
TheCall->setArg(1, OrigArg1);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-20 06:10:17 +08:00
|
|
|
if (OrigArg0->isTypeDependent() || OrigArg1->isTypeDependent())
|
|
|
|
return false;
|
|
|
|
|
2007-12-20 08:26:33 +08:00
|
|
|
// If the common type isn't a real floating type, then the arguments were
|
|
|
|
// invalid for this operation.
|
|
|
|
if (!Res->isRealFloatingType())
|
2009-09-09 23:08:12 +08:00
|
|
|
return Diag(OrigArg0->getLocStart(),
|
2008-11-19 13:08:23 +08:00
|
|
|
diag::err_typecheck_call_invalid_ordered_compare)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< OrigArg0->getType() << OrigArg1->getType()
|
2008-11-19 13:08:23 +08:00
|
|
|
<< SourceRange(OrigArg0->getLocStart(), OrigArg1->getLocEnd());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-20 08:26:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-09-01 04:06:00 +08:00
|
|
|
/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isnan and
|
|
|
|
/// friends. This is declared to take (...), so we have to check everything.
|
|
|
|
bool Sema::SemaBuiltinUnaryFP(CallExpr *TheCall) {
|
|
|
|
if (TheCall->getNumArgs() < 1)
|
|
|
|
return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
|
|
|
|
<< 0 /*function call*/;
|
|
|
|
if (TheCall->getNumArgs() > 1)
|
2009-09-09 23:08:12 +08:00
|
|
|
return Diag(TheCall->getArg(1)->getLocStart(),
|
2009-09-01 04:06:00 +08:00
|
|
|
diag::err_typecheck_call_too_many_args)
|
|
|
|
<< 0 /*function call*/
|
|
|
|
<< SourceRange(TheCall->getArg(1)->getLocStart(),
|
|
|
|
(*(TheCall->arg_end()-1))->getLocEnd());
|
|
|
|
|
|
|
|
Expr *OrigArg = TheCall->getArg(0);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-01 04:06:00 +08:00
|
|
|
if (OrigArg->isTypeDependent())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// This operation requires a floating-point number
|
|
|
|
if (!OrigArg->getType()->isRealFloatingType())
|
2009-09-09 23:08:12 +08:00
|
|
|
return Diag(OrigArg->getLocStart(),
|
2009-09-01 04:06:00 +08:00
|
|
|
diag::err_typecheck_call_invalid_unary_fp)
|
|
|
|
<< OrigArg->getType() << OrigArg->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-01 04:06:00 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-05-20 16:23:37 +08:00
|
|
|
bool Sema::SemaBuiltinStackAddress(CallExpr *TheCall) {
|
|
|
|
// The signature for these builtins is exact; the only thing we need
|
|
|
|
// to check is that the argument is a constant.
|
|
|
|
SourceLocation Loc;
|
2009-05-20 06:10:17 +08:00
|
|
|
if (!TheCall->getArg(0)->isTypeDependent() &&
|
|
|
|
!TheCall->getArg(0)->isValueDependent() &&
|
|
|
|
!TheCall->getArg(0)->isIntegerConstantExpr(Context, &Loc))
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(Loc, diag::err_stack_const_level) << TheCall->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-20 16:23:37 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-05-15 03:38:39 +08:00
|
|
|
/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector.
|
|
|
|
// This is declared to take (...), so we have to check everything.
|
2009-01-19 08:08:26 +08:00
|
|
|
Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
|
2008-05-15 03:38:39 +08:00
|
|
|
if (TheCall->getNumArgs() < 3)
|
2009-01-19 08:08:26 +08:00
|
|
|
return ExprError(Diag(TheCall->getLocEnd(),
|
|
|
|
diag::err_typecheck_call_too_few_args)
|
|
|
|
<< 0 /*function call*/ << TheCall->getSourceRange());
|
2008-05-15 03:38:39 +08:00
|
|
|
|
2009-05-20 06:10:17 +08:00
|
|
|
unsigned numElements = std::numeric_limits<unsigned>::max();
|
|
|
|
if (!TheCall->getArg(0)->isTypeDependent() &&
|
|
|
|
!TheCall->getArg(1)->isTypeDependent()) {
|
|
|
|
QualType FAType = TheCall->getArg(0)->getType();
|
|
|
|
QualType SAType = TheCall->getArg(1)->getType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-20 06:10:17 +08:00
|
|
|
if (!FAType->isVectorType() || !SAType->isVectorType()) {
|
|
|
|
Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector)
|
2009-09-09 23:08:12 +08:00
|
|
|
<< SourceRange(TheCall->getArg(0)->getLocStart(),
|
2009-05-20 06:10:17 +08:00
|
|
|
TheCall->getArg(1)->getLocEnd());
|
|
|
|
return ExprError();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
if (!Context.hasSameUnqualifiedType(FAType, SAType)) {
|
2009-05-20 06:10:17 +08:00
|
|
|
Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
|
2009-09-09 23:08:12 +08:00
|
|
|
<< SourceRange(TheCall->getArg(0)->getLocStart(),
|
2009-05-20 06:10:17 +08:00
|
|
|
TheCall->getArg(1)->getLocEnd());
|
|
|
|
return ExprError();
|
|
|
|
}
|
2008-05-15 03:38:39 +08:00
|
|
|
|
2009-09-22 07:43:11 +08:00
|
|
|
numElements = FAType->getAs<VectorType>()->getNumElements();
|
2009-05-20 06:10:17 +08:00
|
|
|
if (TheCall->getNumArgs() != numElements+2) {
|
|
|
|
if (TheCall->getNumArgs() < numElements+2)
|
|
|
|
return ExprError(Diag(TheCall->getLocEnd(),
|
|
|
|
diag::err_typecheck_call_too_few_args)
|
|
|
|
<< 0 /*function call*/ << TheCall->getSourceRange());
|
2009-01-19 08:08:26 +08:00
|
|
|
return ExprError(Diag(TheCall->getLocEnd(),
|
2009-05-20 06:10:17 +08:00
|
|
|
diag::err_typecheck_call_too_many_args)
|
|
|
|
<< 0 /*function call*/ << TheCall->getSourceRange());
|
|
|
|
}
|
2008-05-15 03:38:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 2; i < TheCall->getNumArgs(); i++) {
|
2009-05-20 06:10:17 +08:00
|
|
|
if (TheCall->getArg(i)->isTypeDependent() ||
|
|
|
|
TheCall->getArg(i)->isValueDependent())
|
|
|
|
continue;
|
|
|
|
|
2008-05-15 03:38:39 +08:00
|
|
|
llvm::APSInt Result(32);
|
2008-08-10 10:05:13 +08:00
|
|
|
if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context))
|
2009-01-19 08:08:26 +08:00
|
|
|
return ExprError(Diag(TheCall->getLocStart(),
|
2008-11-19 13:08:23 +08:00
|
|
|
diag::err_shufflevector_nonconstant_argument)
|
2009-01-19 08:08:26 +08:00
|
|
|
<< TheCall->getArg(i)->getSourceRange());
|
|
|
|
|
2008-08-10 10:05:13 +08:00
|
|
|
if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2)
|
2009-01-19 08:08:26 +08:00
|
|
|
return ExprError(Diag(TheCall->getLocStart(),
|
2008-11-19 13:08:23 +08:00
|
|
|
diag::err_shufflevector_argument_too_large)
|
2009-01-19 08:08:26 +08:00
|
|
|
<< TheCall->getArg(i)->getSourceRange());
|
2008-05-15 03:38:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::SmallVector<Expr*, 32> exprs;
|
|
|
|
|
2008-08-10 10:05:13 +08:00
|
|
|
for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) {
|
2008-05-15 03:38:39 +08:00
|
|
|
exprs.push_back(TheCall->getArg(i));
|
|
|
|
TheCall->setArg(i, 0);
|
|
|
|
}
|
|
|
|
|
2009-08-12 10:10:25 +08:00
|
|
|
return Owned(new (Context) ShuffleVectorExpr(Context, exprs.begin(),
|
|
|
|
exprs.size(), exprs[0]->getType(),
|
2009-02-07 09:47:29 +08:00
|
|
|
TheCall->getCallee()->getLocStart(),
|
|
|
|
TheCall->getRParenLoc()));
|
2008-05-15 03:38:39 +08:00
|
|
|
}
|
2007-12-20 07:59:04 +08:00
|
|
|
|
2008-07-22 06:59:13 +08:00
|
|
|
/// SemaBuiltinPrefetch - Handle __builtin_prefetch.
|
|
|
|
// This is declared to take (const void*, ...) and can take two
|
|
|
|
// optional constant int args.
|
|
|
|
bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) {
|
2008-11-19 13:08:23 +08:00
|
|
|
unsigned NumArgs = TheCall->getNumArgs();
|
2008-07-22 06:59:13 +08:00
|
|
|
|
2008-11-19 13:08:23 +08:00
|
|
|
if (NumArgs > 3)
|
|
|
|
return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_many_args)
|
2008-11-22 02:44:24 +08:00
|
|
|
<< 0 /*function call*/ << TheCall->getSourceRange();
|
2008-07-22 06:59:13 +08:00
|
|
|
|
|
|
|
// Argument 0 is checked for us and the remaining arguments must be
|
|
|
|
// constant integers.
|
2008-11-19 13:08:23 +08:00
|
|
|
for (unsigned i = 1; i != NumArgs; ++i) {
|
2008-07-22 06:59:13 +08:00
|
|
|
Expr *Arg = TheCall->getArg(i);
|
2009-05-20 06:10:17 +08:00
|
|
|
if (Arg->isTypeDependent())
|
|
|
|
continue;
|
|
|
|
|
2009-12-04 08:30:06 +08:00
|
|
|
if (!Arg->getType()->isIntegralType())
|
|
|
|
return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_arg_type)
|
2009-09-23 14:06:36 +08:00
|
|
|
<< Arg->getSourceRange();
|
2009-05-20 06:10:17 +08:00
|
|
|
|
2009-12-04 08:30:06 +08:00
|
|
|
ImpCastExprToType(Arg, Context.IntTy, CastExpr::CK_IntegralCast);
|
|
|
|
TheCall->setArg(i, Arg);
|
|
|
|
|
2009-05-20 06:10:17 +08:00
|
|
|
if (Arg->isValueDependent())
|
|
|
|
continue;
|
|
|
|
|
2009-12-04 08:30:06 +08:00
|
|
|
llvm::APSInt Result;
|
2009-05-20 06:10:17 +08:00
|
|
|
if (!Arg->isIntegerConstantExpr(Result, Context))
|
2009-12-04 08:30:06 +08:00
|
|
|
return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_arg_ice)
|
2009-05-20 06:10:17 +08:00
|
|
|
<< SourceRange(Arg->getLocStart(), Arg->getLocEnd());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-07-22 06:59:13 +08:00
|
|
|
// FIXME: gcc issues a warning and rewrites these to 0. These
|
|
|
|
// seems especially odd for the third argument since the default
|
|
|
|
// is 3.
|
2008-11-19 13:08:23 +08:00
|
|
|
if (i == 1) {
|
2009-12-04 08:30:06 +08:00
|
|
|
if (Result.getLimitedValue() > 1)
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
|
2009-09-23 14:06:36 +08:00
|
|
|
<< "0" << "1" << Arg->getSourceRange();
|
2008-07-22 06:59:13 +08:00
|
|
|
} else {
|
2009-12-04 08:30:06 +08:00
|
|
|
if (Result.getLimitedValue() > 3)
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
|
2009-09-23 14:06:36 +08:00
|
|
|
<< "0" << "3" << Arg->getSourceRange();
|
2008-07-22 06:59:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-19 13:08:23 +08:00
|
|
|
return false;
|
2008-07-22 06:59:13 +08:00
|
|
|
}
|
|
|
|
|
2009-09-23 14:06:36 +08:00
|
|
|
/// SemaBuiltinEHReturnDataRegNo - Handle __builtin_eh_return_data_regno, the
|
|
|
|
/// operand must be an integer constant.
|
|
|
|
bool Sema::SemaBuiltinEHReturnDataRegNo(CallExpr *TheCall) {
|
|
|
|
llvm::APSInt Result;
|
|
|
|
if (!TheCall->getArg(0)->isIntegerConstantExpr(Result, Context))
|
|
|
|
return Diag(TheCall->getLocStart(), diag::err_expr_not_ice)
|
|
|
|
<< TheCall->getArg(0)->getSourceRange();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-04 05:13:56 +08:00
|
|
|
/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr,
|
|
|
|
/// int type). This simply type checks that type is one of the defined
|
|
|
|
/// constants (0-3).
|
2009-12-23 11:49:37 +08:00
|
|
|
// For compatability check 0-3, llvm only handles 0 and 2.
|
2008-09-04 05:13:56 +08:00
|
|
|
bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) {
|
|
|
|
Expr *Arg = TheCall->getArg(1);
|
2009-05-20 06:10:17 +08:00
|
|
|
if (Arg->isTypeDependent())
|
|
|
|
return false;
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType ArgType = Arg->getType();
|
2009-09-22 07:43:11 +08:00
|
|
|
const BuiltinType *BT = ArgType->getAs<BuiltinType>();
|
2008-09-04 05:13:56 +08:00
|
|
|
llvm::APSInt Result(32);
|
2009-05-20 06:10:17 +08:00
|
|
|
if (!BT || BT->getKind() != BuiltinType::Int)
|
|
|
|
return Diag(TheCall->getLocStart(), diag::err_object_size_invalid_argument)
|
|
|
|
<< SourceRange(Arg->getLocStart(), Arg->getLocEnd());
|
|
|
|
|
|
|
|
if (Arg->isValueDependent())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!Arg->isIntegerConstantExpr(Result, Context)) {
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(TheCall->getLocStart(), diag::err_object_size_invalid_argument)
|
|
|
|
<< SourceRange(Arg->getLocStart(), Arg->getLocEnd());
|
2008-09-04 05:13:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) {
|
2008-11-19 13:08:23 +08:00
|
|
|
return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
|
|
|
|
<< "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
|
2008-09-04 05:13:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-05-03 14:04:26 +08:00
|
|
|
/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
|
2009-05-03 12:46:36 +08:00
|
|
|
/// This checks that val is a constant 1.
|
|
|
|
bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
|
|
|
|
Expr *Arg = TheCall->getArg(1);
|
2009-05-20 06:10:17 +08:00
|
|
|
if (Arg->isTypeDependent() || Arg->isValueDependent())
|
|
|
|
return false;
|
|
|
|
|
2009-05-03 12:46:36 +08:00
|
|
|
llvm::APSInt Result(32);
|
|
|
|
if (!Arg->isIntegerConstantExpr(Result, Context) || Result != 1)
|
|
|
|
return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val)
|
|
|
|
<< SourceRange(Arg->getLocStart(), Arg->getLocEnd());
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-01-13 07:09:09 +08:00
|
|
|
// Handle i > 1 ? "x" : "y", recursivelly
|
2009-03-21 05:35:28 +08:00
|
|
|
bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
|
|
|
|
bool HasVAListArg,
|
2009-02-15 02:57:46 +08:00
|
|
|
unsigned format_idx, unsigned firstDataArg) {
|
2009-05-20 06:10:17 +08:00
|
|
|
if (E->isTypeDependent() || E->isValueDependent())
|
|
|
|
return false;
|
2009-01-13 07:09:09 +08:00
|
|
|
|
|
|
|
switch (E->getStmtClass()) {
|
|
|
|
case Stmt::ConditionalOperatorClass: {
|
2009-03-21 05:35:28 +08:00
|
|
|
const ConditionalOperator *C = cast<ConditionalOperator>(E);
|
2009-12-22 14:00:13 +08:00
|
|
|
return SemaCheckStringLiteral(C->getTrueExpr(), TheCall,
|
2009-02-15 02:57:46 +08:00
|
|
|
HasVAListArg, format_idx, firstDataArg)
|
2009-01-13 07:09:09 +08:00
|
|
|
&& SemaCheckStringLiteral(C->getRHS(), TheCall,
|
2009-02-15 02:57:46 +08:00
|
|
|
HasVAListArg, format_idx, firstDataArg);
|
2009-01-13 07:09:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case Stmt::ImplicitCastExprClass: {
|
2009-03-21 05:35:28 +08:00
|
|
|
const ImplicitCastExpr *Expr = cast<ImplicitCastExpr>(E);
|
2009-01-13 07:09:09 +08:00
|
|
|
return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg,
|
2009-02-15 02:57:46 +08:00
|
|
|
format_idx, firstDataArg);
|
2009-01-13 07:09:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case Stmt::ParenExprClass: {
|
2009-03-21 05:35:28 +08:00
|
|
|
const ParenExpr *Expr = cast<ParenExpr>(E);
|
2009-01-13 07:09:09 +08:00
|
|
|
return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg,
|
2009-02-15 02:57:46 +08:00
|
|
|
format_idx, firstDataArg);
|
2009-01-13 07:09:09 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 05:35:28 +08:00
|
|
|
case Stmt::DeclRefExprClass: {
|
|
|
|
const DeclRefExpr *DR = cast<DeclRefExpr>(E);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 05:35:28 +08:00
|
|
|
// As an exception, do not flag errors for variables binding to
|
|
|
|
// const string literals.
|
|
|
|
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
|
|
|
|
bool isConstant = false;
|
|
|
|
QualType T = DR->getType();
|
|
|
|
|
|
|
|
if (const ArrayType *AT = Context.getAsArrayType(T)) {
|
|
|
|
isConstant = AT->getElementType().isConstant(Context);
|
2009-08-05 05:02:39 +08:00
|
|
|
} else if (const PointerType *PT = T->getAs<PointerType>()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
isConstant = T.isConstant(Context) &&
|
2009-03-21 05:35:28 +08:00
|
|
|
PT->getPointeeType().isConstant(Context);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 05:35:28 +08:00
|
|
|
if (isConstant) {
|
2010-02-02 04:16:42 +08:00
|
|
|
if (const Expr *Init = VD->getAnyInitializer())
|
2009-03-21 05:35:28 +08:00
|
|
|
return SemaCheckStringLiteral(Init, TheCall,
|
|
|
|
HasVAListArg, format_idx, firstDataArg);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-29 03:55:58 +08:00
|
|
|
// For vprintf* functions (i.e., HasVAListArg==true), we add a
|
|
|
|
// special check to see if the format string is a function parameter
|
|
|
|
// of the function calling the printf function. If the function
|
|
|
|
// has an attribute indicating it is a printf-like function, then we
|
|
|
|
// should suppress warnings concerning non-literals being used in a call
|
|
|
|
// to a vprintf function. For example:
|
|
|
|
//
|
|
|
|
// void
|
|
|
|
// logmessage(char const *fmt __attribute__ (format (printf, 1, 2)), ...){
|
|
|
|
// va_list ap;
|
|
|
|
// va_start(ap, fmt);
|
|
|
|
// vprintf(fmt, ap); // Do NOT emit a warning about "fmt".
|
|
|
|
// ...
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// FIXME: We don't have full attribute support yet, so just check to see
|
|
|
|
// if the argument is a DeclRefExpr that references a parameter. We'll
|
|
|
|
// add proper support for checking the attribute later.
|
|
|
|
if (HasVAListArg)
|
|
|
|
if (isa<ParmVarDecl>(VD))
|
|
|
|
return true;
|
2009-03-21 05:35:28 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 05:35:28 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-01-13 07:09:09 +08:00
|
|
|
|
2009-06-27 12:05:33 +08:00
|
|
|
case Stmt::CallExprClass: {
|
|
|
|
const CallExpr *CE = cast<CallExpr>(E);
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const ImplicitCastExpr *ICE
|
2009-06-27 12:05:33 +08:00
|
|
|
= dyn_cast<ImplicitCastExpr>(CE->getCallee())) {
|
|
|
|
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) {
|
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
|
2009-06-30 10:34:44 +08:00
|
|
|
if (const FormatArgAttr *FA = FD->getAttr<FormatArgAttr>()) {
|
2009-06-27 12:05:33 +08:00
|
|
|
unsigned ArgIndex = FA->getFormatIdx();
|
|
|
|
const Expr *Arg = CE->getArg(ArgIndex - 1);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg,
|
2009-06-27 12:05:33 +08:00
|
|
|
format_idx, firstDataArg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-27 12:05:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-03-21 05:35:28 +08:00
|
|
|
case Stmt::ObjCStringLiteralClass:
|
|
|
|
case Stmt::StringLiteralClass: {
|
|
|
|
const StringLiteral *StrE = NULL;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 05:35:28 +08:00
|
|
|
if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E))
|
2009-01-13 07:09:09 +08:00
|
|
|
StrE = ObjCFExpr->getString();
|
|
|
|
else
|
2009-03-21 05:35:28 +08:00
|
|
|
StrE = cast<StringLiteral>(E);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-13 07:09:09 +08:00
|
|
|
if (StrE) {
|
2009-09-09 23:08:12 +08:00
|
|
|
CheckPrintfString(StrE, E, TheCall, HasVAListArg, format_idx,
|
2009-02-15 02:57:46 +08:00
|
|
|
firstDataArg);
|
2009-01-13 07:09:09 +08:00
|
|
|
return true;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-13 07:09:09 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 05:35:28 +08:00
|
|
|
default:
|
|
|
|
return false;
|
2009-01-13 07:09:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-22 02:48:51 +08:00
|
|
|
void
|
2009-09-09 23:08:12 +08:00
|
|
|
Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
|
|
|
|
const CallExpr *TheCall) {
|
2009-05-22 02:48:51 +08:00
|
|
|
for (NonNullAttr::iterator i = NonNull->begin(), e = NonNull->end();
|
|
|
|
i != e; ++i) {
|
2009-05-26 02:23:36 +08:00
|
|
|
const Expr *ArgExpr = TheCall->getArg(*i);
|
2009-09-25 12:25:58 +08:00
|
|
|
if (ArgExpr->isNullPointerConstant(Context,
|
|
|
|
Expr::NPC_ValueDependentIsNotNull))
|
2009-05-26 02:23:36 +08:00
|
|
|
Diag(TheCall->getCallee()->getLocStart(), diag::warn_null_arg)
|
|
|
|
<< ArgExpr->getSourceRange();
|
2009-05-22 02:48:51 +08:00
|
|
|
}
|
|
|
|
}
|
2009-01-13 07:09:09 +08:00
|
|
|
|
2007-08-11 04:18:51 +08:00
|
|
|
/// CheckPrintfArguments - Check calls to printf (and similar functions) for
|
2009-09-09 23:08:12 +08:00
|
|
|
/// correct use of format strings.
|
2007-08-15 01:39:48 +08:00
|
|
|
///
|
|
|
|
/// HasVAListArg - A predicate indicating whether the printf-like
|
|
|
|
/// function is passed an explicit va_arg argument (e.g., vprintf)
|
|
|
|
///
|
|
|
|
/// format_idx - The index into Args for the format string.
|
|
|
|
///
|
|
|
|
/// Improper format strings to functions in the printf family can be
|
|
|
|
/// the source of bizarre bugs and very serious security holes. A
|
|
|
|
/// good source of information is available in the following paper
|
|
|
|
/// (which includes additional references):
|
2007-08-11 04:18:51 +08:00
|
|
|
///
|
|
|
|
/// FormatGuard: Automatic Protection From printf Format String
|
|
|
|
/// Vulnerabilities, Proceedings of the 10th USENIX Security Symposium, 2001.
|
2007-08-15 01:39:48 +08:00
|
|
|
///
|
|
|
|
/// Functionality implemented:
|
|
|
|
///
|
|
|
|
/// We can statically check the following properties for string
|
|
|
|
/// literal format strings for non v.*printf functions (where the
|
|
|
|
/// arguments are passed directly):
|
|
|
|
//
|
|
|
|
/// (1) Are the number of format conversions equal to the number of
|
|
|
|
/// data arguments?
|
|
|
|
///
|
|
|
|
/// (2) Does each format conversion correctly match the type of the
|
|
|
|
/// corresponding data argument? (TODO)
|
|
|
|
///
|
|
|
|
/// Moreover, for all printf functions we can:
|
|
|
|
///
|
|
|
|
/// (3) Check for a missing format string (when not caught by type checking).
|
|
|
|
///
|
|
|
|
/// (4) Check for no-operation flags; e.g. using "#" with format
|
|
|
|
/// conversion 'c' (TODO)
|
|
|
|
///
|
|
|
|
/// (5) Check the use of '%n', a major source of security holes.
|
|
|
|
///
|
|
|
|
/// (6) Check for malformed format conversions that don't specify anything.
|
|
|
|
///
|
|
|
|
/// (7) Check for empty format strings. e.g: printf("");
|
|
|
|
///
|
|
|
|
/// (8) Check that the format string is a wide literal.
|
|
|
|
///
|
|
|
|
/// All of these checks can be done by parsing the format string.
|
|
|
|
///
|
|
|
|
/// For now, we ONLY do (1), (3), (5), (6), (7), and (8).
|
2007-08-11 04:18:51 +08:00
|
|
|
void
|
2009-09-09 23:08:12 +08:00
|
|
|
Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg,
|
2009-02-15 02:57:46 +08:00
|
|
|
unsigned format_idx, unsigned firstDataArg) {
|
2009-03-21 05:35:28 +08:00
|
|
|
const Expr *Fn = TheCall->getCallee();
|
2007-12-28 13:29:59 +08:00
|
|
|
|
2009-11-18 02:02:24 +08:00
|
|
|
// The way the format attribute works in GCC, the implicit this argument
|
|
|
|
// of member functions is counted. However, it doesn't appear in our own
|
|
|
|
// lists, so decrement format_idx in that case.
|
|
|
|
if (isa<CXXMemberCallExpr>(TheCall)) {
|
|
|
|
// Catch a format attribute mistakenly referring to the object argument.
|
|
|
|
if (format_idx == 0)
|
|
|
|
return;
|
|
|
|
--format_idx;
|
|
|
|
if(firstDataArg != 0)
|
|
|
|
--firstDataArg;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// CHECK: printf-like function is called with no format string.
|
2007-12-28 13:29:59 +08:00
|
|
|
if (format_idx >= TheCall->getNumArgs()) {
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(TheCall->getRParenLoc(), diag::warn_printf_missing_format_string)
|
|
|
|
<< Fn->getSourceRange();
|
2007-08-15 01:39:48 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 05:35:28 +08:00
|
|
|
const Expr *OrigFormatExpr = TheCall->getArg(format_idx)->IgnoreParenCasts();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-11 04:18:51 +08:00
|
|
|
// CHECK: format string is not a string literal.
|
2009-09-09 23:08:12 +08:00
|
|
|
//
|
2007-08-15 01:39:48 +08:00
|
|
|
// Dynamically generated format strings are difficult to
|
|
|
|
// automatically vet at compile time. Requiring that format strings
|
|
|
|
// are string literals: (1) permits the checking of format strings by
|
|
|
|
// the compiler and thereby (2) can practically remove the source of
|
|
|
|
// many format string exploits.
|
2008-06-17 02:00:42 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// Format string can be either ObjC string (e.g. @"%d") or
|
2008-06-17 02:00:42 +08:00
|
|
|
// C string (e.g. "%d")
|
2009-09-09 23:08:12 +08:00
|
|
|
// ObjC string uses the same format specifiers as C string, so we can use
|
2008-06-17 02:00:42 +08:00
|
|
|
// the same format string checking logic for both ObjC and C strings.
|
2009-04-29 12:49:34 +08:00
|
|
|
if (SemaCheckStringLiteral(OrigFormatExpr, TheCall, HasVAListArg, format_idx,
|
|
|
|
firstDataArg))
|
|
|
|
return; // Literal format string found, check done!
|
|
|
|
|
2009-04-29 12:59:47 +08:00
|
|
|
// If there are no arguments specified, warn with -Wformat-security, otherwise
|
|
|
|
// warn only with -Wformat-nonliteral.
|
|
|
|
if (TheCall->getNumArgs() == format_idx+1)
|
2009-09-09 23:08:12 +08:00
|
|
|
Diag(TheCall->getArg(format_idx)->getLocStart(),
|
2009-04-29 12:59:47 +08:00
|
|
|
diag::warn_printf_nonliteral_noargs)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
|
|
|
else
|
2009-09-09 23:08:12 +08:00
|
|
|
Diag(TheCall->getArg(format_idx)->getLocStart(),
|
2009-04-29 12:59:47 +08:00
|
|
|
diag::warn_printf_nonliteral)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
2009-01-13 07:09:09 +08:00
|
|
|
}
|
|
|
|
|
2010-01-29 07:39:18 +08:00
|
|
|
namespace {
|
2010-02-05 04:46:58 +08:00
|
|
|
class CheckPrintfHandler : public analyze_printf::FormatStringHandler {
|
2010-01-29 07:39:18 +08:00
|
|
|
Sema &S;
|
|
|
|
const StringLiteral *FExpr;
|
|
|
|
const Expr *OrigFormatExpr;
|
|
|
|
unsigned NumConversions;
|
|
|
|
const unsigned NumDataArgs;
|
|
|
|
const bool IsObjCLiteral;
|
|
|
|
const char *Beg; // Start of format string.
|
2010-01-29 09:06:55 +08:00
|
|
|
const bool HasVAListArg;
|
|
|
|
const CallExpr *TheCall;
|
|
|
|
unsigned FormatIdx;
|
2010-01-29 07:39:18 +08:00
|
|
|
public:
|
|
|
|
CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
|
|
|
|
const Expr *origFormatExpr,
|
|
|
|
unsigned numDataArgs, bool isObjCLiteral,
|
2010-01-29 09:06:55 +08:00
|
|
|
const char *beg, bool hasVAListArg,
|
|
|
|
const CallExpr *theCall, unsigned formatIdx)
|
2010-01-29 07:39:18 +08:00
|
|
|
: S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
|
|
|
|
NumConversions(0), NumDataArgs(numDataArgs),
|
2010-01-29 09:06:55 +08:00
|
|
|
IsObjCLiteral(isObjCLiteral), Beg(beg),
|
|
|
|
HasVAListArg(hasVAListArg),
|
|
|
|
TheCall(theCall), FormatIdx(formatIdx) {}
|
2010-01-29 09:50:07 +08:00
|
|
|
|
|
|
|
void DoneProcessing();
|
2010-01-29 11:16:21 +08:00
|
|
|
|
|
|
|
void HandleIncompleteFormatSpecifier(const char *startSpecifier,
|
|
|
|
unsigned specifierLen);
|
2010-01-29 10:40:24 +08:00
|
|
|
|
2010-02-05 04:46:58 +08:00
|
|
|
void
|
|
|
|
HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
|
|
|
|
const char *startSpecifier,
|
|
|
|
unsigned specifierLen);
|
2010-01-29 10:40:24 +08:00
|
|
|
|
2010-01-29 07:39:18 +08:00
|
|
|
void HandleNullChar(const char *nullCharacter);
|
|
|
|
|
|
|
|
bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
|
|
|
|
const char *startSpecifier,
|
|
|
|
unsigned specifierLen);
|
|
|
|
private:
|
2010-01-30 04:55:36 +08:00
|
|
|
SourceRange getFormatStringRange();
|
|
|
|
SourceRange getFormatSpecifierRange(const char *startSpecifier,
|
|
|
|
unsigned specifierLen);
|
2010-01-29 07:39:18 +08:00
|
|
|
SourceLocation getLocationOfByte(const char *x);
|
2010-01-29 09:06:55 +08:00
|
|
|
|
|
|
|
bool HandleAmount(const analyze_printf::OptionalAmount &Amt,
|
2010-01-30 04:55:36 +08:00
|
|
|
unsigned MissingArgDiag, unsigned BadTypeDiag,
|
|
|
|
const char *startSpecifier, unsigned specifierLen);
|
2010-01-29 09:06:55 +08:00
|
|
|
|
2010-01-30 08:49:51 +08:00
|
|
|
bool MatchType(QualType A, QualType B, bool ignoreSign);
|
|
|
|
|
2010-01-29 09:06:55 +08:00
|
|
|
const Expr *getDataArg(unsigned i) const;
|
2010-01-29 07:39:18 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2010-01-30 04:55:36 +08:00
|
|
|
SourceRange CheckPrintfHandler::getFormatStringRange() {
|
2010-01-29 07:39:18 +08:00
|
|
|
return OrigFormatExpr->getSourceRange();
|
|
|
|
}
|
|
|
|
|
2010-01-30 04:55:36 +08:00
|
|
|
SourceRange CheckPrintfHandler::
|
|
|
|
getFormatSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
|
|
|
|
return SourceRange(getLocationOfByte(startSpecifier),
|
|
|
|
getLocationOfByte(startSpecifier+specifierLen-1));
|
|
|
|
}
|
|
|
|
|
2010-01-29 07:39:18 +08:00
|
|
|
SourceLocation CheckPrintfHandler::getLocationOfByte(const char *x) {
|
|
|
|
return S.getLocationOfStringLiteralByte(FExpr, x - Beg);
|
|
|
|
}
|
|
|
|
|
2010-01-29 11:16:21 +08:00
|
|
|
void CheckPrintfHandler::
|
|
|
|
HandleIncompleteFormatSpecifier(const char *startSpecifier,
|
|
|
|
unsigned specifierLen) {
|
|
|
|
SourceLocation Loc = getLocationOfByte(startSpecifier);
|
|
|
|
S.Diag(Loc, diag::warn_printf_incomplete_specifier)
|
2010-01-30 04:55:36 +08:00
|
|
|
<< getFormatSpecifierRange(startSpecifier, specifierLen);
|
2010-01-29 11:16:21 +08:00
|
|
|
}
|
|
|
|
|
2010-01-29 10:40:24 +08:00
|
|
|
void CheckPrintfHandler::
|
|
|
|
HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
|
|
|
|
const char *startSpecifier,
|
|
|
|
unsigned specifierLen) {
|
|
|
|
|
|
|
|
++NumConversions;
|
2010-01-29 11:16:21 +08:00
|
|
|
const analyze_printf::ConversionSpecifier &CS =
|
|
|
|
FS.getConversionSpecifier();
|
|
|
|
SourceLocation Loc = getLocationOfByte(CS.getStart());
|
2010-01-29 10:40:24 +08:00
|
|
|
S.Diag(Loc, diag::warn_printf_invalid_conversion)
|
2010-01-29 11:16:21 +08:00
|
|
|
<< llvm::StringRef(CS.getStart(), CS.getLength())
|
2010-01-30 04:55:36 +08:00
|
|
|
<< getFormatSpecifierRange(startSpecifier, specifierLen);
|
2010-01-29 10:40:24 +08:00
|
|
|
}
|
|
|
|
|
2010-01-29 07:39:18 +08:00
|
|
|
void CheckPrintfHandler::HandleNullChar(const char *nullCharacter) {
|
|
|
|
// The presence of a null character is likely an error.
|
|
|
|
S.Diag(getLocationOfByte(nullCharacter),
|
|
|
|
diag::warn_printf_format_string_contains_null_char)
|
2010-01-30 04:55:36 +08:00
|
|
|
<< getFormatStringRange();
|
2010-01-29 07:39:18 +08:00
|
|
|
}
|
|
|
|
|
2010-01-29 09:06:55 +08:00
|
|
|
const Expr *CheckPrintfHandler::getDataArg(unsigned i) const {
|
|
|
|
return TheCall->getArg(FormatIdx + i);
|
|
|
|
}
|
|
|
|
|
2010-01-30 08:49:51 +08:00
|
|
|
bool CheckPrintfHandler::MatchType(QualType A, QualType B, bool ignoreSign) {
|
|
|
|
A = S.Context.getCanonicalType(A).getUnqualifiedType();
|
|
|
|
B = S.Context.getCanonicalType(B).getUnqualifiedType();
|
|
|
|
|
|
|
|
if (A == B)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (ignoreSign) {
|
|
|
|
if (const BuiltinType *BT = B->getAs<BuiltinType>()) {
|
|
|
|
switch (BT->getKind()) {
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case BuiltinType::Char_S:
|
|
|
|
case BuiltinType::SChar:
|
|
|
|
return A == S.Context.UnsignedCharTy;
|
|
|
|
case BuiltinType::Char_U:
|
|
|
|
case BuiltinType::UChar:
|
|
|
|
return A == S.Context.SignedCharTy;
|
|
|
|
case BuiltinType::Short:
|
|
|
|
return A == S.Context.UnsignedShortTy;
|
|
|
|
case BuiltinType::UShort:
|
|
|
|
return A == S.Context.ShortTy;
|
|
|
|
case BuiltinType::Int:
|
|
|
|
return A == S.Context.UnsignedIntTy;
|
|
|
|
case BuiltinType::UInt:
|
|
|
|
return A == S.Context.IntTy;
|
|
|
|
case BuiltinType::Long:
|
|
|
|
return A == S.Context.UnsignedLongTy;
|
|
|
|
case BuiltinType::ULong:
|
|
|
|
return A == S.Context.LongTy;
|
|
|
|
case BuiltinType::LongLong:
|
|
|
|
return A == S.Context.UnsignedLongLongTy;
|
|
|
|
case BuiltinType::ULongLong:
|
|
|
|
return A == S.Context.LongLongTy;
|
|
|
|
}
|
|
|
|
return A == B;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-01-29 09:06:55 +08:00
|
|
|
bool
|
|
|
|
CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt,
|
|
|
|
unsigned MissingArgDiag,
|
2010-01-30 04:55:36 +08:00
|
|
|
unsigned BadTypeDiag,
|
|
|
|
const char *startSpecifier,
|
|
|
|
unsigned specifierLen) {
|
2010-01-29 09:06:55 +08:00
|
|
|
|
|
|
|
if (Amt.hasDataArgument()) {
|
|
|
|
++NumConversions;
|
|
|
|
if (!HasVAListArg) {
|
|
|
|
if (NumConversions > NumDataArgs) {
|
|
|
|
S.Diag(getLocationOfByte(Amt.getStart()), MissingArgDiag)
|
2010-01-30 04:55:36 +08:00
|
|
|
<< getFormatSpecifierRange(startSpecifier, specifierLen);
|
2010-01-29 09:06:55 +08:00
|
|
|
// Don't do any more checking. We will just emit
|
|
|
|
// spurious errors.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Type check the data argument. It should be an 'int'.
|
2010-01-30 07:32:22 +08:00
|
|
|
// Although not in conformance with C99, we also allow the argument to be
|
|
|
|
// an 'unsigned int' as that is a reasonably safe case. GCC also
|
|
|
|
// doesn't emit a warning for that case.
|
2010-01-29 09:06:55 +08:00
|
|
|
const Expr *Arg = getDataArg(NumConversions);
|
|
|
|
QualType T = Arg->getType();
|
2010-01-30 08:49:51 +08:00
|
|
|
if (!MatchType(T, S.Context.IntTy, true)) {
|
2010-01-29 09:06:55 +08:00
|
|
|
S.Diag(getLocationOfByte(Amt.getStart()), BadTypeDiag)
|
2010-01-30 08:49:51 +08:00
|
|
|
<< S.Context.IntTy << T
|
|
|
|
<< getFormatSpecifierRange(startSpecifier, specifierLen)
|
|
|
|
<< Arg->getSourceRange();
|
2010-01-29 09:06:55 +08:00
|
|
|
// Don't do any more checking. We will just emit
|
|
|
|
// spurious errors.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-29 07:39:18 +08:00
|
|
|
bool
|
|
|
|
CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
|
|
|
|
const char *startSpecifier,
|
|
|
|
unsigned specifierLen) {
|
|
|
|
|
|
|
|
using namespace analyze_printf;
|
|
|
|
const ConversionSpecifier &CS = FS.getConversionSpecifier();
|
|
|
|
|
2010-01-29 09:06:55 +08:00
|
|
|
// First check if the field width, precision, and conversion specifier
|
|
|
|
// have matching data arguments.
|
|
|
|
if (!HandleAmount(FS.getFieldWidth(),
|
|
|
|
diag::warn_printf_asterisk_width_missing_arg,
|
2010-01-30 04:55:36 +08:00
|
|
|
diag::warn_printf_asterisk_width_wrong_type,
|
|
|
|
startSpecifier, specifierLen)) {
|
2010-01-29 09:06:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!HandleAmount(FS.getPrecision(),
|
|
|
|
diag::warn_printf_asterisk_precision_missing_arg,
|
2010-01-30 04:55:36 +08:00
|
|
|
diag::warn_printf_asterisk_precision_wrong_type,
|
|
|
|
startSpecifier, specifierLen)) {
|
2010-01-29 09:06:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-01-29 07:39:18 +08:00
|
|
|
// Check for using an Objective-C specific conversion specifier
|
|
|
|
// in a non-ObjC literal.
|
|
|
|
if (!IsObjCLiteral && CS.isObjCArg()) {
|
2010-01-29 10:40:24 +08:00
|
|
|
HandleInvalidConversionSpecifier(FS, startSpecifier, specifierLen);
|
2010-01-29 07:39:18 +08:00
|
|
|
|
|
|
|
// Continue checking the other format specifiers.
|
|
|
|
return true;
|
|
|
|
}
|
2010-01-30 04:55:36 +08:00
|
|
|
|
|
|
|
if (!CS.consumesDataArgument()) {
|
|
|
|
// FIXME: Technically specifying a precision or field width here
|
|
|
|
// makes no sense. Worth issuing a warning at some point.
|
|
|
|
return true;
|
|
|
|
}
|
2010-01-29 09:35:25 +08:00
|
|
|
|
2010-01-29 10:40:24 +08:00
|
|
|
++NumConversions;
|
|
|
|
|
2010-01-29 09:35:25 +08:00
|
|
|
// Are we using '%n'? Issue a warning about this being
|
|
|
|
// a possible security issue.
|
|
|
|
if (CS.getKind() == ConversionSpecifier::OutIntPtrArg) {
|
|
|
|
S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back)
|
2010-01-30 04:55:36 +08:00
|
|
|
<< getFormatSpecifierRange(startSpecifier, specifierLen);
|
2010-01-29 09:35:25 +08:00
|
|
|
// Continue checking the other format specifiers.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-29 09:43:31 +08:00
|
|
|
|
|
|
|
// The remaining checks depend on the data arguments.
|
|
|
|
if (HasVAListArg)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (NumConversions > NumDataArgs) {
|
|
|
|
S.Diag(getLocationOfByte(CS.getStart()),
|
|
|
|
diag::warn_printf_insufficient_data_args)
|
2010-01-30 04:55:36 +08:00
|
|
|
<< getFormatSpecifierRange(startSpecifier, specifierLen);
|
2010-01-29 09:43:31 +08:00
|
|
|
// Don't do any more checking.
|
|
|
|
return false;
|
|
|
|
}
|
2010-01-30 08:49:51 +08:00
|
|
|
|
|
|
|
// Now type check the data expression that matches the
|
|
|
|
// format specifier.
|
|
|
|
const Expr *Ex = getDataArg(NumConversions);
|
|
|
|
const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context);
|
2010-02-02 03:28:15 +08:00
|
|
|
|
2010-01-30 08:49:51 +08:00
|
|
|
if (const QualType *T = ATR.getSpecificType()) {
|
|
|
|
if (!MatchType(*T, Ex->getType(), true)) {
|
2010-02-02 03:28:15 +08:00
|
|
|
// Check if we didn't match because of an implicit cast from a 'char'
|
|
|
|
// or 'short' to an 'int'. This is done because printf is a varargs
|
|
|
|
// function.
|
|
|
|
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex))
|
2010-02-02 03:38:10 +08:00
|
|
|
if (ICE->getType() == S.Context.IntTy)
|
|
|
|
if (MatchType(*T, ICE->getSubExpr()->getType(), true))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
S.Diag(getLocationOfByte(CS.getStart()),
|
|
|
|
diag::warn_printf_conversion_argument_type_mismatch)
|
2010-02-05 04:46:58 +08:00
|
|
|
<< *T << Ex->getType();
|
|
|
|
// << getFormatSpecifierRange(startSpecifier, specifierLen)
|
|
|
|
// << Ex->getSourceRange();
|
2010-01-30 08:49:51 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2010-01-29 07:39:18 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-01-29 09:50:07 +08:00
|
|
|
void CheckPrintfHandler::DoneProcessing() {
|
|
|
|
// Does the number of data arguments exceed the number of
|
|
|
|
// format conversions in the format string?
|
|
|
|
if (!HasVAListArg && NumConversions < NumDataArgs)
|
|
|
|
S.Diag(getDataArg(NumConversions+1)->getLocStart(),
|
|
|
|
diag::warn_printf_too_many_data_args)
|
2010-01-30 04:55:36 +08:00
|
|
|
<< getFormatStringRange();
|
2010-01-29 09:50:07 +08:00
|
|
|
}
|
2010-01-29 07:39:18 +08:00
|
|
|
|
2010-01-30 04:55:36 +08:00
|
|
|
void Sema::CheckPrintfString(const StringLiteral *FExpr,
|
|
|
|
const Expr *OrigFormatExpr,
|
|
|
|
const CallExpr *TheCall, bool HasVAListArg,
|
|
|
|
unsigned format_idx, unsigned firstDataArg) {
|
2010-01-28 09:18:22 +08:00
|
|
|
|
2010-01-29 07:39:18 +08:00
|
|
|
// CHECK: is the format string a wide literal?
|
|
|
|
if (FExpr->isWide()) {
|
|
|
|
Diag(FExpr->getLocStart(),
|
|
|
|
diag::warn_printf_format_string_is_wide_literal)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Str - The format string. NOTE: this is NOT null-terminated!
|
|
|
|
const char *Str = FExpr->getStrData();
|
2010-01-28 09:18:22 +08:00
|
|
|
|
2010-01-29 07:39:18 +08:00
|
|
|
// CHECK: empty format string?
|
|
|
|
unsigned StrLen = FExpr->getByteLength();
|
|
|
|
|
|
|
|
if (StrLen == 0) {
|
|
|
|
Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CheckPrintfHandler H(*this, FExpr, OrigFormatExpr,
|
|
|
|
TheCall->getNumArgs() - firstDataArg,
|
2010-01-29 09:06:55 +08:00
|
|
|
isa<ObjCStringLiteral>(OrigFormatExpr), Str,
|
|
|
|
HasVAListArg, TheCall, format_idx);
|
2010-01-29 07:39:18 +08:00
|
|
|
|
2010-02-05 04:46:58 +08:00
|
|
|
if (!analyze_printf::ParseFormatString(H, Str, Str + StrLen))
|
2010-01-29 11:16:21 +08:00
|
|
|
H.DoneProcessing();
|
2010-01-28 09:18:22 +08:00
|
|
|
}
|
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
//===--- CHECK: Return Address of Stack Variable --------------------------===//
|
|
|
|
|
|
|
|
static DeclRefExpr* EvalVal(Expr *E);
|
|
|
|
static DeclRefExpr* EvalAddr(Expr* E);
|
|
|
|
|
|
|
|
/// CheckReturnStackAddr - Check if a return statement returns the address
|
|
|
|
/// of a stack variable.
|
|
|
|
void
|
|
|
|
Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
|
|
|
|
SourceLocation ReturnLoc) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
// Perform checking for returned stack addresses.
|
2008-09-06 06:11:13 +08:00
|
|
|
if (lhsType->isPointerType() || lhsType->isBlockPointerType()) {
|
2007-08-18 00:46:58 +08:00
|
|
|
if (DeclRefExpr *DR = EvalAddr(RetValExp))
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(DR->getLocStart(), diag::warn_ret_stack_addr)
|
2008-11-24 05:45:46 +08:00
|
|
|
<< DR->getDecl()->getDeclName() << RetValExp->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-09-17 06:25:10 +08:00
|
|
|
// Skip over implicit cast expressions when checking for block expressions.
|
2009-09-08 08:36:37 +08:00
|
|
|
RetValExp = RetValExp->IgnoreParenCasts();
|
2008-09-17 06:25:10 +08:00
|
|
|
|
2009-10-30 12:01:58 +08:00
|
|
|
if (BlockExpr *C = dyn_cast<BlockExpr>(RetValExp))
|
2009-04-17 08:09:41 +08:00
|
|
|
if (C->hasBlockDeclRefExprs())
|
|
|
|
Diag(C->getLocStart(), diag::err_ret_local_block)
|
|
|
|
<< C->getSourceRange();
|
2009-10-30 12:01:58 +08:00
|
|
|
|
|
|
|
if (AddrLabelExpr *ALE = dyn_cast<AddrLabelExpr>(RetValExp))
|
|
|
|
Diag(ALE->getLocStart(), diag::warn_ret_addr_label)
|
|
|
|
<< ALE->getSourceRange();
|
|
|
|
|
2009-08-05 05:02:39 +08:00
|
|
|
} else if (lhsType->isReferenceType()) {
|
|
|
|
// Perform checking for stack values returned by reference.
|
2008-10-28 03:41:14 +08:00
|
|
|
// Check for a reference to the stack
|
|
|
|
if (DeclRefExpr *DR = EvalVal(RetValExp))
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(DR->getLocStart(), diag::warn_ret_stack_ref)
|
2008-11-24 05:45:46 +08:00
|
|
|
<< DR->getDecl()->getDeclName() << RetValExp->getSourceRange();
|
2007-08-18 00:46:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// EvalAddr - EvalAddr and EvalVal are mutually recursive functions that
|
|
|
|
/// check if the expression in a return statement evaluates to an address
|
|
|
|
/// to a location on the stack. The recursion is used to traverse the
|
|
|
|
/// AST of the return expression, with recursion backtracking when we
|
|
|
|
/// encounter a subexpression that (1) clearly does not lead to the address
|
|
|
|
/// of a stack variable or (2) is something we cannot determine leads to
|
|
|
|
/// the address of a stack variable based on such local checking.
|
|
|
|
///
|
2007-08-29 01:02:55 +08:00
|
|
|
/// EvalAddr processes expressions that are pointers that are used as
|
|
|
|
/// references (and not L-values). EvalVal handles all other values.
|
2009-09-09 23:08:12 +08:00
|
|
|
/// At the base case of the recursion is a check for a DeclRefExpr* in
|
2007-08-18 00:46:58 +08:00
|
|
|
/// the refers to a stack variable.
|
|
|
|
///
|
|
|
|
/// This implementation handles:
|
|
|
|
///
|
|
|
|
/// * pointer-to-pointer casts
|
|
|
|
/// * implicit conversions from array references to pointers
|
|
|
|
/// * taking the address of fields
|
|
|
|
/// * arbitrary interplay between "&" and "*" operators
|
|
|
|
/// * pointer arithmetic from an address of a stack variable
|
|
|
|
/// * taking the address of an array element where the array is on the stack
|
|
|
|
static DeclRefExpr* EvalAddr(Expr *E) {
|
|
|
|
// We should only be called for evaluating pointer expressions.
|
2009-08-18 00:35:33 +08:00
|
|
|
assert((E->getType()->isAnyPointerType() ||
|
2008-09-06 06:11:13 +08:00
|
|
|
E->getType()->isBlockPointerType() ||
|
2008-01-08 03:49:32 +08:00
|
|
|
E->getType()->isObjCQualifiedIdType()) &&
|
2007-12-28 13:31:15 +08:00
|
|
|
"EvalAddr only works on pointers");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
// Our "symbolic interpreter" is just a dispatch off the currently
|
|
|
|
// viewed AST node. We then recursively traverse the AST by calling
|
|
|
|
// EvalAddr and EvalVal appropriately.
|
|
|
|
switch (E->getStmtClass()) {
|
2007-12-28 13:31:15 +08:00
|
|
|
case Stmt::ParenExprClass:
|
|
|
|
// Ignore parentheses.
|
|
|
|
return EvalAddr(cast<ParenExpr>(E)->getSubExpr());
|
2007-08-18 00:46:58 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
case Stmt::UnaryOperatorClass: {
|
|
|
|
// The only unary operator that make sense to handle here
|
|
|
|
// is AddrOf. All others don't make sense as pointers.
|
|
|
|
UnaryOperator *U = cast<UnaryOperator>(E);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
if (U->getOpcode() == UnaryOperator::AddrOf)
|
|
|
|
return EvalVal(U->getSubExpr());
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
case Stmt::BinaryOperatorClass: {
|
|
|
|
// Handle pointer arithmetic. All other binary operators are not valid
|
|
|
|
// in this context.
|
|
|
|
BinaryOperator *B = cast<BinaryOperator>(E);
|
|
|
|
BinaryOperator::Opcode op = B->getOpcode();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
if (op != BinaryOperator::Add && op != BinaryOperator::Sub)
|
|
|
|
return NULL;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
Expr *Base = B->getLHS();
|
2007-12-01 03:04:31 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
// Determine which argument is the real pointer base. It could be
|
|
|
|
// the RHS argument instead of the LHS.
|
|
|
|
if (!Base->getType()->isPointerType()) Base = B->getRHS();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
assert (Base->getType()->isPointerType());
|
|
|
|
return EvalAddr(Base);
|
|
|
|
}
|
2008-09-11 03:17:48 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
// For conditional operators we need to see if either the LHS or RHS are
|
|
|
|
// valid DeclRefExpr*s. If one of them is valid, we return it.
|
|
|
|
case Stmt::ConditionalOperatorClass: {
|
|
|
|
ConditionalOperator *C = cast<ConditionalOperator>(E);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
// Handle the GNU extension for missing LHS.
|
|
|
|
if (Expr *lhsExpr = C->getLHS())
|
|
|
|
if (DeclRefExpr* LHS = EvalAddr(lhsExpr))
|
|
|
|
return LHS;
|
2007-08-18 00:46:58 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
return EvalAddr(C->getRHS());
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-07 08:49:01 +08:00
|
|
|
// For casts, we need to handle conversions from arrays to
|
|
|
|
// pointer values, and pointer-to-pointer conversions.
|
2008-10-28 03:41:14 +08:00
|
|
|
case Stmt::ImplicitCastExprClass:
|
2008-10-28 23:36:24 +08:00
|
|
|
case Stmt::CStyleCastExprClass:
|
2008-10-28 03:41:14 +08:00
|
|
|
case Stmt::CXXFunctionalCastExprClass: {
|
2008-08-19 07:01:59 +08:00
|
|
|
Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
|
2008-08-07 08:49:01 +08:00
|
|
|
QualType T = SubExpr->getType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-09-06 06:11:13 +08:00
|
|
|
if (SubExpr->getType()->isPointerType() ||
|
|
|
|
SubExpr->getType()->isBlockPointerType() ||
|
|
|
|
SubExpr->getType()->isObjCQualifiedIdType())
|
2007-12-28 13:31:15 +08:00
|
|
|
return EvalAddr(SubExpr);
|
2008-08-07 08:49:01 +08:00
|
|
|
else if (T->isArrayType())
|
|
|
|
return EvalVal(SubExpr);
|
2007-12-28 13:31:15 +08:00
|
|
|
else
|
2008-08-07 08:49:01 +08:00
|
|
|
return 0;
|
2007-12-28 13:31:15 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
// C++ casts. For dynamic casts, static casts, and const casts, we
|
|
|
|
// are always converting from a pointer-to-pointer, so we just blow
|
2008-10-28 03:41:14 +08:00
|
|
|
// through the cast. In the case the dynamic cast doesn't fail (and
|
|
|
|
// return NULL), we take the conservative route and report cases
|
2007-12-28 13:31:15 +08:00
|
|
|
// where we return the address of a stack variable. For Reinterpre
|
2008-10-28 03:41:14 +08:00
|
|
|
// FIXME: The comment about is wrong; we're not always converting
|
|
|
|
// from pointer to pointer. I'm guessing that this code should also
|
2009-09-09 23:08:12 +08:00
|
|
|
// handle references to objects.
|
|
|
|
case Stmt::CXXStaticCastExprClass:
|
|
|
|
case Stmt::CXXDynamicCastExprClass:
|
2008-10-28 03:41:14 +08:00
|
|
|
case Stmt::CXXConstCastExprClass:
|
|
|
|
case Stmt::CXXReinterpretCastExprClass: {
|
|
|
|
Expr *S = cast<CXXNamedCastExpr>(E)->getSubExpr();
|
2008-09-06 06:11:13 +08:00
|
|
|
if (S->getType()->isPointerType() || S->getType()->isBlockPointerType())
|
2007-12-28 13:31:15 +08:00
|
|
|
return EvalAddr(S);
|
2007-08-18 00:46:58 +08:00
|
|
|
else
|
|
|
|
return NULL;
|
2007-12-28 13:31:15 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
// Everything else: we simply don't reason about them.
|
|
|
|
default:
|
|
|
|
return NULL;
|
2007-08-18 00:46:58 +08:00
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
|
|
|
|
/// EvalVal - This function is complements EvalAddr in the mutual recursion.
|
|
|
|
/// See the comments for EvalAddr for more details.
|
|
|
|
static DeclRefExpr* EvalVal(Expr *E) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-29 01:02:55 +08:00
|
|
|
// We should only be called for evaluating non-pointer expressions, or
|
|
|
|
// expressions with a pointer type that are not used as references but instead
|
|
|
|
// are l-values (e.g., DeclRefExpr with a pointer type).
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
// Our "symbolic interpreter" is just a dispatch off the currently
|
|
|
|
// viewed AST node. We then recursively traverse the AST by calling
|
|
|
|
// EvalAddr and EvalVal appropriately.
|
|
|
|
switch (E->getStmtClass()) {
|
2009-10-24 02:54:35 +08:00
|
|
|
case Stmt::DeclRefExprClass: {
|
2007-08-18 00:46:58 +08:00
|
|
|
// DeclRefExpr: the base case. When we hit a DeclRefExpr we are looking
|
|
|
|
// at code that refers to a variable's name. We check if it has local
|
|
|
|
// storage within the function, and if so, return the expression.
|
|
|
|
DeclRefExpr *DR = cast<DeclRefExpr>(E);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
|
2009-09-09 23:08:12 +08:00
|
|
|
if (V->hasLocalStorage() && !V->getType()->isReferenceType()) return DR;
|
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
case Stmt::ParenExprClass:
|
|
|
|
// Ignore parentheses.
|
|
|
|
return EvalVal(cast<ParenExpr>(E)->getSubExpr());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
case Stmt::UnaryOperatorClass: {
|
|
|
|
// The only unary operator that make sense to handle here
|
|
|
|
// is Deref. All others don't resolve to a "name." This includes
|
|
|
|
// handling all sorts of rvalues passed to a unary operator.
|
|
|
|
UnaryOperator *U = cast<UnaryOperator>(E);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
if (U->getOpcode() == UnaryOperator::Deref)
|
|
|
|
return EvalAddr(U->getSubExpr());
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
case Stmt::ArraySubscriptExprClass: {
|
|
|
|
// Array subscripts are potential references to data on the stack. We
|
|
|
|
// retrieve the DeclRefExpr* for the array variable if it indeed
|
|
|
|
// has local storage.
|
2007-08-21 00:18:38 +08:00
|
|
|
return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase());
|
2007-08-18 00:46:58 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
case Stmt::ConditionalOperatorClass: {
|
|
|
|
// For conditional operators we need to see if either the LHS or RHS are
|
|
|
|
// non-NULL DeclRefExpr's. If one is non-NULL, we return it.
|
|
|
|
ConditionalOperator *C = cast<ConditionalOperator>(E);
|
|
|
|
|
2007-12-01 03:04:31 +08:00
|
|
|
// Handle the GNU extension for missing LHS.
|
|
|
|
if (Expr *lhsExpr = C->getLHS())
|
|
|
|
if (DeclRefExpr *LHS = EvalVal(lhsExpr))
|
|
|
|
return LHS;
|
|
|
|
|
|
|
|
return EvalVal(C->getRHS());
|
2007-08-18 00:46:58 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
// Accesses to members are potential references to data on the stack.
|
2009-09-01 07:41:50 +08:00
|
|
|
case Stmt::MemberExprClass: {
|
2007-08-18 00:46:58 +08:00
|
|
|
MemberExpr *M = cast<MemberExpr>(E);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
// Check for indirect access. We only want direct field accesses.
|
|
|
|
if (!M->isArrow())
|
|
|
|
return EvalVal(M->getBase());
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-18 00:46:58 +08:00
|
|
|
// Everything else: we simply don't reason about them.
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2007-11-25 08:58:00 +08:00
|
|
|
|
|
|
|
//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
|
|
|
|
|
|
|
|
/// Check for comparisons of floating point operands using != and ==.
|
|
|
|
/// Issue a warning if these are no self-comparisons, as they are not likely
|
|
|
|
/// to do what the programmer intended.
|
|
|
|
void Sema::CheckFloatComparison(SourceLocation loc, Expr* lex, Expr *rex) {
|
|
|
|
bool EmitWarning = true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-18 00:57:34 +08:00
|
|
|
Expr* LeftExprSansParen = lex->IgnoreParens();
|
2008-01-18 01:55:13 +08:00
|
|
|
Expr* RightExprSansParen = rex->IgnoreParens();
|
2007-11-25 08:58:00 +08:00
|
|
|
|
|
|
|
// Special case: check for x == x (which is OK).
|
|
|
|
// Do not emit warnings for such cases.
|
|
|
|
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen))
|
|
|
|
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RightExprSansParen))
|
|
|
|
if (DRL->getDecl() == DRR->getDecl())
|
|
|
|
EmitWarning = false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
2007-11-29 08:59:04 +08:00
|
|
|
// Special case: check for comparisons against literals that can be exactly
|
|
|
|
// represented by APFloat. In such cases, do not emit a warning. This
|
|
|
|
// is a heuristic: often comparison against such literals are used to
|
|
|
|
// detect if a value in a variable has not changed. This clearly can
|
|
|
|
// lead to false negatives.
|
|
|
|
if (EmitWarning) {
|
|
|
|
if (FloatingLiteral* FLL = dyn_cast<FloatingLiteral>(LeftExprSansParen)) {
|
|
|
|
if (FLL->isExact())
|
|
|
|
EmitWarning = false;
|
2009-08-05 05:02:39 +08:00
|
|
|
} else
|
2007-11-29 08:59:04 +08:00
|
|
|
if (FloatingLiteral* FLR = dyn_cast<FloatingLiteral>(RightExprSansParen)){
|
|
|
|
if (FLR->isExact())
|
|
|
|
EmitWarning = false;
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-25 08:58:00 +08:00
|
|
|
// Check for comparisons with builtin types.
|
2009-01-19 08:08:26 +08:00
|
|
|
if (EmitWarning)
|
2007-11-25 08:58:00 +08:00
|
|
|
if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen))
|
2009-02-15 02:57:46 +08:00
|
|
|
if (CL->isBuiltinCall(Context))
|
2007-11-25 08:58:00 +08:00
|
|
|
EmitWarning = false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-19 08:08:26 +08:00
|
|
|
if (EmitWarning)
|
2007-11-25 08:58:00 +08:00
|
|
|
if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen))
|
2009-02-15 02:57:46 +08:00
|
|
|
if (CR->isBuiltinCall(Context))
|
2007-11-25 08:58:00 +08:00
|
|
|
EmitWarning = false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-25 08:58:00 +08:00
|
|
|
// Emit the diagnostic.
|
|
|
|
if (EmitWarning)
|
2008-11-19 13:08:23 +08:00
|
|
|
Diag(loc, diag::warn_floatingpoint_eq)
|
|
|
|
<< lex->getSourceRange() << rex->getSourceRange();
|
2007-11-25 08:58:00 +08:00
|
|
|
}
|
2010-01-05 07:21:16 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
//===--- CHECK: Integer mixed-sign comparisons (-Wsign-compare) --------===//
|
|
|
|
//===--- CHECK: Lossy implicit conversions (-Wconversion) --------------===//
|
2010-01-05 07:21:16 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
namespace {
|
2010-01-05 07:21:16 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
/// Structure recording the 'active' range of an integer-valued
|
|
|
|
/// expression.
|
|
|
|
struct IntRange {
|
|
|
|
/// The number of bits active in the int.
|
|
|
|
unsigned Width;
|
2010-01-05 07:21:16 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
/// True if the int is known not to have negative values.
|
|
|
|
bool NonNegative;
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
IntRange() {}
|
|
|
|
IntRange(unsigned Width, bool NonNegative)
|
|
|
|
: Width(Width), NonNegative(NonNegative)
|
|
|
|
{}
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// Returns the range of the bool type.
|
|
|
|
static IntRange forBoolType() {
|
|
|
|
return IntRange(1, true);
|
|
|
|
}
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// Returns the range of an integral type.
|
|
|
|
static IntRange forType(ASTContext &C, QualType T) {
|
|
|
|
return forCanonicalType(C, T->getCanonicalTypeInternal().getTypePtr());
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// Returns the range of an integeral type based on its canonical
|
|
|
|
// representation.
|
|
|
|
static IntRange forCanonicalType(ASTContext &C, const Type *T) {
|
|
|
|
assert(T->isCanonicalUnqualified());
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
if (const VectorType *VT = dyn_cast<VectorType>(T))
|
|
|
|
T = VT->getElementType().getTypePtr();
|
|
|
|
if (const ComplexType *CT = dyn_cast<ComplexType>(T))
|
|
|
|
T = CT->getElementType().getTypePtr();
|
|
|
|
if (const EnumType *ET = dyn_cast<EnumType>(T))
|
|
|
|
T = ET->getDecl()->getIntegerType().getTypePtr();
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
const BuiltinType *BT = cast<BuiltinType>(T);
|
|
|
|
assert(BT->isInteger());
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger());
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// Returns the supremum of two ranges: i.e. their conservative merge.
|
|
|
|
static IntRange join(const IntRange &L, const IntRange &R) {
|
|
|
|
return IntRange(std::max(L.Width, R.Width),
|
2010-01-07 06:07:33 +08:00
|
|
|
L.NonNegative && R.NonNegative);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the infinum of two ranges: i.e. their aggressive merge.
|
|
|
|
static IntRange meet(const IntRange &L, const IntRange &R) {
|
|
|
|
return IntRange(std::min(L.Width, R.Width),
|
|
|
|
L.NonNegative || R.NonNegative);
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
2010-01-06 13:24:50 +08:00
|
|
|
};
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) {
|
|
|
|
if (value.isSigned() && value.isNegative())
|
|
|
|
return IntRange(value.getMinSignedBits(), false);
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
if (value.getBitWidth() > MaxWidth)
|
|
|
|
value.trunc(MaxWidth);
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// isNonNegative() just checks the sign bit without considering
|
|
|
|
// signedness.
|
|
|
|
return IntRange(value.getActiveBits(), true);
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
|
|
|
|
2010-01-07 06:57:21 +08:00
|
|
|
IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty,
|
2010-01-06 13:24:50 +08:00
|
|
|
unsigned MaxWidth) {
|
|
|
|
if (result.isInt())
|
|
|
|
return GetValueRange(C, result.getInt(), MaxWidth);
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
if (result.isVector()) {
|
2010-01-07 06:57:21 +08:00
|
|
|
IntRange R = GetValueRange(C, result.getVectorElt(0), Ty, MaxWidth);
|
|
|
|
for (unsigned i = 1, e = result.getVectorLength(); i != e; ++i) {
|
|
|
|
IntRange El = GetValueRange(C, result.getVectorElt(i), Ty, MaxWidth);
|
|
|
|
R = IntRange::join(R, El);
|
|
|
|
}
|
2010-01-06 13:24:50 +08:00
|
|
|
return R;
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
if (result.isComplexInt()) {
|
|
|
|
IntRange R = GetValueRange(C, result.getComplexIntReal(), MaxWidth);
|
|
|
|
IntRange I = GetValueRange(C, result.getComplexIntImag(), MaxWidth);
|
|
|
|
return IntRange::join(R, I);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This can happen with lossless casts to intptr_t of "based" lvalues.
|
|
|
|
// Assume it might use arbitrary bits.
|
2010-01-07 06:57:21 +08:00
|
|
|
// FIXME: The only reason we need to pass the type in here is to get
|
|
|
|
// the sign right on this one case. It would be nice if APValue
|
|
|
|
// preserved this.
|
2010-01-06 13:24:50 +08:00
|
|
|
assert(result.isLValue());
|
2010-01-07 06:57:21 +08:00
|
|
|
return IntRange(MaxWidth, Ty->isUnsignedIntegerType());
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
/// Pseudo-evaluate the given integer expression, estimating the
|
|
|
|
/// range of values it might take.
|
|
|
|
///
|
|
|
|
/// \param MaxWidth - the width to which the value will be truncated
|
|
|
|
IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
|
2010-01-05 07:31:57 +08:00
|
|
|
E = E->IgnoreParens();
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// Try a full evaluation first.
|
|
|
|
Expr::EvalResult result;
|
|
|
|
if (E->Evaluate(result, C))
|
2010-01-07 06:57:21 +08:00
|
|
|
return GetValueRange(C, result.Val, E->getType(), MaxWidth);
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// I think we only want to look through implicit casts here; if the
|
|
|
|
// user has an explicit widening cast, we should treat the value as
|
|
|
|
// being of the new, wider type.
|
|
|
|
if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
|
|
|
|
if (CE->getCastKind() == CastExpr::CK_NoOp)
|
|
|
|
return GetExprRange(C, CE->getSubExpr(), MaxWidth);
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
IntRange OutputTypeRange = IntRange::forType(C, CE->getType());
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-07 06:07:33 +08:00
|
|
|
bool isIntegerCast = (CE->getCastKind() == CastExpr::CK_IntegralCast);
|
|
|
|
if (!isIntegerCast && CE->getCastKind() == CastExpr::CK_Unknown)
|
|
|
|
isIntegerCast = CE->getSubExpr()->getType()->isIntegerType();
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// Assume that non-integer casts can span the full range of the type.
|
2010-01-07 06:07:33 +08:00
|
|
|
if (!isIntegerCast)
|
2010-01-06 13:24:50 +08:00
|
|
|
return OutputTypeRange;
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
IntRange SubRange
|
|
|
|
= GetExprRange(C, CE->getSubExpr(),
|
|
|
|
std::min(MaxWidth, OutputTypeRange.Width));
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// Bail out if the subexpr's range is as wide as the cast type.
|
|
|
|
if (SubRange.Width >= OutputTypeRange.Width)
|
|
|
|
return OutputTypeRange;
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// Otherwise, we take the smaller width, and we're non-negative if
|
|
|
|
// either the output type or the subexpr is.
|
|
|
|
return IntRange(SubRange.Width,
|
|
|
|
SubRange.NonNegative || OutputTypeRange.NonNegative);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
|
|
|
|
// If we can fold the condition, just take that operand.
|
|
|
|
bool CondResult;
|
|
|
|
if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C))
|
|
|
|
return GetExprRange(C, CondResult ? CO->getTrueExpr()
|
|
|
|
: CO->getFalseExpr(),
|
|
|
|
MaxWidth);
|
|
|
|
|
|
|
|
// Otherwise, conservatively merge.
|
|
|
|
IntRange L = GetExprRange(C, CO->getTrueExpr(), MaxWidth);
|
|
|
|
IntRange R = GetExprRange(C, CO->getFalseExpr(), MaxWidth);
|
|
|
|
return IntRange::join(L, R);
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
|
|
|
|
switch (BO->getOpcode()) {
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// Boolean-valued operations are single-bit and positive.
|
2010-01-05 07:31:57 +08:00
|
|
|
case BinaryOperator::LAnd:
|
|
|
|
case BinaryOperator::LOr:
|
|
|
|
case BinaryOperator::LT:
|
|
|
|
case BinaryOperator::GT:
|
|
|
|
case BinaryOperator::LE:
|
|
|
|
case BinaryOperator::GE:
|
|
|
|
case BinaryOperator::EQ:
|
|
|
|
case BinaryOperator::NE:
|
2010-01-06 13:24:50 +08:00
|
|
|
return IntRange::forBoolType();
|
2010-01-05 07:31:57 +08:00
|
|
|
|
|
|
|
// Operations with opaque sources are black-listed.
|
|
|
|
case BinaryOperator::PtrMemD:
|
|
|
|
case BinaryOperator::PtrMemI:
|
2010-01-06 13:24:50 +08:00
|
|
|
return IntRange::forType(C, E->getType());
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-07 06:07:33 +08:00
|
|
|
// Bitwise-and uses the *infinum* of the two source ranges.
|
|
|
|
case BinaryOperator::And:
|
|
|
|
return IntRange::meet(GetExprRange(C, BO->getLHS(), MaxWidth),
|
|
|
|
GetExprRange(C, BO->getRHS(), MaxWidth));
|
|
|
|
|
2010-01-05 07:31:57 +08:00
|
|
|
// Left shift gets black-listed based on a judgement call.
|
|
|
|
case BinaryOperator::Shl:
|
2010-01-06 13:24:50 +08:00
|
|
|
return IntRange::forType(C, E->getType());
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-07 06:07:33 +08:00
|
|
|
// Right shift by a constant can narrow its left argument.
|
|
|
|
case BinaryOperator::Shr: {
|
|
|
|
IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth);
|
|
|
|
|
|
|
|
// If the shift amount is a positive constant, drop the width by
|
|
|
|
// that much.
|
|
|
|
llvm::APSInt shift;
|
|
|
|
if (BO->getRHS()->isIntegerConstantExpr(shift, C) &&
|
|
|
|
shift.isNonNegative()) {
|
|
|
|
unsigned zext = shift.getZExtValue();
|
|
|
|
if (zext >= L.Width)
|
|
|
|
L.Width = (L.NonNegative ? 0 : 1);
|
|
|
|
else
|
|
|
|
L.Width -= zext;
|
|
|
|
}
|
|
|
|
|
|
|
|
return L;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Comma acts as its right operand.
|
2010-01-05 07:31:57 +08:00
|
|
|
case BinaryOperator::Comma:
|
2010-01-06 13:24:50 +08:00
|
|
|
return GetExprRange(C, BO->getRHS(), MaxWidth);
|
|
|
|
|
2010-01-07 06:07:33 +08:00
|
|
|
// Black-list pointer subtractions.
|
2010-01-05 07:31:57 +08:00
|
|
|
case BinaryOperator::Sub:
|
|
|
|
if (BO->getLHS()->getType()->isPointerType())
|
2010-01-06 13:24:50 +08:00
|
|
|
return IntRange::forType(C, E->getType());
|
2010-01-05 07:31:57 +08:00
|
|
|
// fallthrough
|
|
|
|
|
|
|
|
default:
|
2010-01-06 13:24:50 +08:00
|
|
|
break;
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
2010-01-06 13:24:50 +08:00
|
|
|
|
|
|
|
// Treat every other operator as if it were closed on the
|
|
|
|
// narrowest type that encompasses both operands.
|
|
|
|
IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth);
|
|
|
|
IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth);
|
|
|
|
return IntRange::join(L, R);
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
|
|
|
|
switch (UO->getOpcode()) {
|
|
|
|
// Boolean-valued operations are white-listed.
|
|
|
|
case UnaryOperator::LNot:
|
2010-01-06 13:24:50 +08:00
|
|
|
return IntRange::forBoolType();
|
2010-01-05 07:31:57 +08:00
|
|
|
|
|
|
|
// Operations with opaque sources are black-listed.
|
|
|
|
case UnaryOperator::Deref:
|
|
|
|
case UnaryOperator::AddrOf: // should be impossible
|
|
|
|
case UnaryOperator::OffsetOf:
|
2010-01-06 13:24:50 +08:00
|
|
|
return IntRange::forType(C, E->getType());
|
2010-01-05 07:31:57 +08:00
|
|
|
|
|
|
|
default:
|
2010-01-06 13:24:50 +08:00
|
|
|
return GetExprRange(C, UO->getSubExpr(), MaxWidth);
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
FieldDecl *BitField = E->getBitField();
|
|
|
|
if (BitField) {
|
|
|
|
llvm::APSInt BitWidthAP = BitField->getBitWidth()->EvaluateAsInt(C);
|
|
|
|
unsigned BitWidth = BitWidthAP.getZExtValue();
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
return IntRange(BitWidth, BitField->getType()->isUnsignedIntegerType());
|
|
|
|
}
|
|
|
|
|
|
|
|
return IntRange::forType(C, E->getType());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks whether the given value, which currently has the given
|
|
|
|
/// source semantics, has the same value when coerced through the
|
|
|
|
/// target semantics.
|
|
|
|
bool IsSameFloatAfterCast(const llvm::APFloat &value,
|
|
|
|
const llvm::fltSemantics &Src,
|
|
|
|
const llvm::fltSemantics &Tgt) {
|
|
|
|
llvm::APFloat truncated = value;
|
|
|
|
|
|
|
|
bool ignored;
|
|
|
|
truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored);
|
|
|
|
truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored);
|
|
|
|
|
|
|
|
return truncated.bitwiseIsEqual(value);
|
2010-01-05 07:31:57 +08:00
|
|
|
}
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
/// Checks whether the given value, which currently has the given
|
|
|
|
/// source semantics, has the same value when coerced through the
|
|
|
|
/// target semantics.
|
|
|
|
///
|
|
|
|
/// The value might be a vector of floats (or a complex number).
|
|
|
|
bool IsSameFloatAfterCast(const APValue &value,
|
|
|
|
const llvm::fltSemantics &Src,
|
|
|
|
const llvm::fltSemantics &Tgt) {
|
|
|
|
if (value.isFloat())
|
|
|
|
return IsSameFloatAfterCast(value.getFloat(), Src, Tgt);
|
|
|
|
|
|
|
|
if (value.isVector()) {
|
|
|
|
for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
|
|
|
|
if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(value.isComplexFloat());
|
|
|
|
return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) &&
|
|
|
|
IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
2010-01-05 07:21:16 +08:00
|
|
|
/// \brief Implements -Wsign-compare.
|
|
|
|
///
|
|
|
|
/// \param lex the left-hand expression
|
|
|
|
/// \param rex the right-hand expression
|
|
|
|
/// \param OpLoc the location of the joining operator
|
|
|
|
/// \param Equality whether this is an "equality-like" join, which
|
|
|
|
/// suppresses the warning in some cases
|
|
|
|
void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
|
|
|
|
const PartialDiagnostic &PD, bool Equality) {
|
|
|
|
// Don't warn if we're in an unevaluated context.
|
|
|
|
if (ExprEvalContexts.back().Context == Unevaluated)
|
|
|
|
return;
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// If either expression is value-dependent, don't warn. We'll get another
|
|
|
|
// chance at instantiation time.
|
|
|
|
if (lex->isValueDependent() || rex->isValueDependent())
|
|
|
|
return;
|
|
|
|
|
2010-01-05 07:21:16 +08:00
|
|
|
QualType lt = lex->getType(), rt = rex->getType();
|
|
|
|
|
|
|
|
// Only warn if both operands are integral.
|
|
|
|
if (!lt->isIntegerType() || !rt->isIntegerType())
|
|
|
|
return;
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// In C, the width of a bitfield determines its type, and the
|
|
|
|
// declared type only contributes the signedness. This duplicates
|
|
|
|
// the work that will later be done by UsualUnaryConversions.
|
|
|
|
// Eventually, this check will be reorganized in a way that avoids
|
|
|
|
// this duplication.
|
|
|
|
if (!getLangOptions().CPlusPlus) {
|
|
|
|
QualType tmp;
|
|
|
|
tmp = Context.isPromotableBitField(lex);
|
|
|
|
if (!tmp.isNull()) lt = tmp;
|
|
|
|
tmp = Context.isPromotableBitField(rex);
|
|
|
|
if (!tmp.isNull()) rt = tmp;
|
|
|
|
}
|
2010-01-05 07:21:16 +08:00
|
|
|
|
|
|
|
// The rule is that the signed operand becomes unsigned, so isolate the
|
|
|
|
// signed operand.
|
2010-01-06 13:24:50 +08:00
|
|
|
Expr *signedOperand = lex, *unsignedOperand = rex;
|
|
|
|
QualType signedType = lt, unsignedType = rt;
|
2010-01-05 07:21:16 +08:00
|
|
|
if (lt->isSignedIntegerType()) {
|
|
|
|
if (rt->isSignedIntegerType()) return;
|
|
|
|
} else {
|
|
|
|
if (!rt->isSignedIntegerType()) return;
|
2010-01-06 13:24:50 +08:00
|
|
|
std::swap(signedOperand, unsignedOperand);
|
|
|
|
std::swap(signedType, unsignedType);
|
2010-01-05 07:21:16 +08:00
|
|
|
}
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
unsigned unsignedWidth = Context.getIntWidth(unsignedType);
|
|
|
|
unsigned signedWidth = Context.getIntWidth(signedType);
|
|
|
|
|
2010-01-05 07:21:16 +08:00
|
|
|
// If the unsigned type is strictly smaller than the signed type,
|
|
|
|
// then (1) the result type will be signed and (2) the unsigned
|
|
|
|
// value will fit fully within the signed type, and thus the result
|
|
|
|
// of the comparison will be exact.
|
2010-01-06 13:24:50 +08:00
|
|
|
if (signedWidth > unsignedWidth)
|
2010-01-05 07:21:16 +08:00
|
|
|
return;
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
// Otherwise, calculate the effective ranges.
|
|
|
|
IntRange signedRange = GetExprRange(Context, signedOperand, signedWidth);
|
|
|
|
IntRange unsignedRange = GetExprRange(Context, unsignedOperand, unsignedWidth);
|
|
|
|
|
|
|
|
// We should never be unable to prove that the unsigned operand is
|
|
|
|
// non-negative.
|
|
|
|
assert(unsignedRange.NonNegative && "unsigned range includes negative?");
|
|
|
|
|
|
|
|
// If the signed operand is non-negative, then the signed->unsigned
|
|
|
|
// conversion won't change it.
|
|
|
|
if (signedRange.NonNegative)
|
2010-01-05 07:21:16 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
// For (in)equality comparisons, if the unsigned operand is a
|
|
|
|
// constant which cannot collide with a overflowed signed operand,
|
|
|
|
// then reinterpreting the signed operand as unsigned will not
|
|
|
|
// change the result of the comparison.
|
2010-01-06 13:24:50 +08:00
|
|
|
if (Equality && unsignedRange.Width < unsignedWidth)
|
2010-01-05 07:21:16 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
Diag(OpLoc, PD)
|
2010-01-06 13:24:50 +08:00
|
|
|
<< lt << rt << lex->getSourceRange() << rex->getSourceRange();
|
2010-01-05 07:21:16 +08:00
|
|
|
}
|
|
|
|
|
2010-01-05 07:31:57 +08:00
|
|
|
/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
|
|
|
|
static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) {
|
|
|
|
S.Diag(E->getExprLoc(), diag) << E->getType() << T << E->getSourceRange();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Implements -Wconversion.
|
|
|
|
void Sema::CheckImplicitConversion(Expr *E, QualType T) {
|
|
|
|
// Don't diagnose in unevaluated contexts.
|
|
|
|
if (ExprEvalContexts.back().Context == Sema::Unevaluated)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Don't diagnose for value-dependent expressions.
|
|
|
|
if (E->isValueDependent())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const Type *Source = Context.getCanonicalType(E->getType()).getTypePtr();
|
|
|
|
const Type *Target = Context.getCanonicalType(T).getTypePtr();
|
|
|
|
|
|
|
|
// Never diagnose implicit casts to bool.
|
|
|
|
if (Target->isSpecificBuiltinType(BuiltinType::Bool))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Strip vector types.
|
|
|
|
if (isa<VectorType>(Source)) {
|
|
|
|
if (!isa<VectorType>(Target))
|
|
|
|
return DiagnoseImpCast(*this, E, T, diag::warn_impcast_vector_scalar);
|
|
|
|
|
|
|
|
Source = cast<VectorType>(Source)->getElementType().getTypePtr();
|
|
|
|
Target = cast<VectorType>(Target)->getElementType().getTypePtr();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Strip complex types.
|
|
|
|
if (isa<ComplexType>(Source)) {
|
|
|
|
if (!isa<ComplexType>(Target))
|
|
|
|
return DiagnoseImpCast(*this, E, T, diag::warn_impcast_complex_scalar);
|
|
|
|
|
|
|
|
Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
|
|
|
|
Target = cast<ComplexType>(Target)->getElementType().getTypePtr();
|
|
|
|
}
|
|
|
|
|
|
|
|
const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source);
|
|
|
|
const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target);
|
|
|
|
|
|
|
|
// If the source is floating point...
|
|
|
|
if (SourceBT && SourceBT->isFloatingPoint()) {
|
|
|
|
// ...and the target is floating point...
|
|
|
|
if (TargetBT && TargetBT->isFloatingPoint()) {
|
|
|
|
// ...then warn if we're dropping FP rank.
|
|
|
|
|
|
|
|
// Builtin FP kinds are ordered by increasing FP rank.
|
|
|
|
if (SourceBT->getKind() > TargetBT->getKind()) {
|
|
|
|
// Don't warn about float constants that are precisely
|
|
|
|
// representable in the target type.
|
|
|
|
Expr::EvalResult result;
|
|
|
|
if (E->Evaluate(result, Context)) {
|
|
|
|
// Value might be a float, a float vector, or a float complex.
|
|
|
|
if (IsSameFloatAfterCast(result.Val,
|
|
|
|
Context.getFloatTypeSemantics(QualType(TargetBT, 0)),
|
|
|
|
Context.getFloatTypeSemantics(QualType(SourceBT, 0))))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DiagnoseImpCast(*this, E, T, diag::warn_impcast_float_precision);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the target is integral, always warn.
|
|
|
|
if ((TargetBT && TargetBT->isInteger()))
|
|
|
|
// TODO: don't warn for integer values?
|
|
|
|
return DiagnoseImpCast(*this, E, T, diag::warn_impcast_float_integer);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
if (!Source->isIntegerType() || !Target->isIntegerType())
|
2010-01-05 07:31:57 +08:00
|
|
|
return;
|
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
IntRange SourceRange = GetExprRange(Context, E, Context.getIntWidth(E->getType()));
|
|
|
|
IntRange TargetRange = IntRange::forCanonicalType(Context, Target);
|
|
|
|
|
|
|
|
// FIXME: also signed<->unsigned?
|
2010-01-05 07:31:57 +08:00
|
|
|
|
2010-01-06 13:24:50 +08:00
|
|
|
if (SourceRange.Width > TargetRange.Width) {
|
2010-01-05 07:31:57 +08:00
|
|
|
// People want to build with -Wshorten-64-to-32 and not -Wconversion
|
|
|
|
// and by god we'll let them.
|
2010-01-06 13:24:50 +08:00
|
|
|
if (SourceRange.Width == 64 && TargetRange.Width == 32)
|
2010-01-05 07:31:57 +08:00
|
|
|
return DiagnoseImpCast(*this, E, T, diag::warn_impcast_integer_64_32);
|
|
|
|
return DiagnoseImpCast(*this, E, T, diag::warn_impcast_integer_precision);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-01-21 11:59:47 +08:00
|
|
|
// MarkLive - Mark all the blocks reachable from e as live. Returns the total
|
|
|
|
// number of blocks just marked live.
|
|
|
|
static unsigned MarkLive(CFGBlock *e, llvm::BitVector &live) {
|
|
|
|
unsigned count = 0;
|
|
|
|
std::queue<CFGBlock*> workq;
|
|
|
|
// Prep work queue
|
|
|
|
live.set(e->getBlockID());
|
|
|
|
++count;
|
|
|
|
workq.push(e);
|
|
|
|
// Solve
|
|
|
|
while (!workq.empty()) {
|
|
|
|
CFGBlock *item = workq.front();
|
|
|
|
workq.pop();
|
|
|
|
for (CFGBlock::succ_iterator I=item->succ_begin(),
|
|
|
|
E=item->succ_end();
|
|
|
|
I != E;
|
|
|
|
++I) {
|
|
|
|
if ((*I) && !live[(*I)->getBlockID()]) {
|
|
|
|
live.set((*I)->getBlockID());
|
|
|
|
++count;
|
|
|
|
workq.push(*I);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2010-01-22 01:21:23 +08:00
|
|
|
static SourceLocation GetUnreachableLoc(CFGBlock &b, SourceRange &R1,
|
|
|
|
SourceRange &R2) {
|
2010-01-21 11:59:47 +08:00
|
|
|
Stmt *S;
|
2010-01-22 03:44:04 +08:00
|
|
|
unsigned sn = 0;
|
|
|
|
R1 = R2 = SourceRange();
|
|
|
|
|
|
|
|
top:
|
|
|
|
if (sn < b.size())
|
|
|
|
S = b[sn].getStmt();
|
2010-01-21 11:59:47 +08:00
|
|
|
else if (b.getTerminator())
|
|
|
|
S = b.getTerminator();
|
|
|
|
else
|
|
|
|
return SourceLocation();
|
|
|
|
|
|
|
|
switch (S->getStmtClass()) {
|
|
|
|
case Expr::BinaryOperatorClass: {
|
2010-01-22 01:21:23 +08:00
|
|
|
BinaryOperator *BO = cast<BinaryOperator>(S);
|
|
|
|
if (BO->getOpcode() == BinaryOperator::Comma) {
|
2010-01-22 03:44:04 +08:00
|
|
|
if (sn+1 < b.size())
|
|
|
|
return b[sn+1].getStmt()->getLocStart();
|
2010-01-21 11:59:47 +08:00
|
|
|
CFGBlock *n = &b;
|
|
|
|
while (1) {
|
|
|
|
if (n->getTerminator())
|
|
|
|
return n->getTerminator()->getLocStart();
|
|
|
|
if (n->succ_size() != 1)
|
|
|
|
return SourceLocation();
|
|
|
|
n = n[0].succ_begin()[0];
|
|
|
|
if (n->pred_size() != 1)
|
|
|
|
return SourceLocation();
|
|
|
|
if (!n->empty())
|
|
|
|
return n[0][0].getStmt()->getLocStart();
|
|
|
|
}
|
|
|
|
}
|
2010-01-22 01:21:23 +08:00
|
|
|
R1 = BO->getLHS()->getSourceRange();
|
|
|
|
R2 = BO->getRHS()->getSourceRange();
|
|
|
|
return BO->getOperatorLoc();
|
|
|
|
}
|
|
|
|
case Expr::UnaryOperatorClass: {
|
|
|
|
const UnaryOperator *UO = cast<UnaryOperator>(S);
|
|
|
|
R1 = UO->getSubExpr()->getSourceRange();
|
|
|
|
return UO->getOperatorLoc();
|
2010-01-21 11:59:47 +08:00
|
|
|
}
|
2010-01-22 01:31:41 +08:00
|
|
|
case Expr::CompoundAssignOperatorClass: {
|
|
|
|
const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S);
|
|
|
|
R1 = CAO->getLHS()->getSourceRange();
|
|
|
|
R2 = CAO->getRHS()->getSourceRange();
|
|
|
|
return CAO->getOperatorLoc();
|
|
|
|
}
|
2010-01-22 03:44:04 +08:00
|
|
|
case Expr::ConditionalOperatorClass: {
|
|
|
|
const ConditionalOperator *CO = cast<ConditionalOperator>(S);
|
|
|
|
return CO->getQuestionLoc();
|
|
|
|
}
|
2010-01-22 07:15:53 +08:00
|
|
|
case Expr::MemberExprClass: {
|
|
|
|
const MemberExpr *ME = cast<MemberExpr>(S);
|
|
|
|
R1 = ME->getSourceRange();
|
|
|
|
return ME->getMemberLoc();
|
|
|
|
}
|
|
|
|
case Expr::ArraySubscriptExprClass: {
|
|
|
|
const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S);
|
|
|
|
R1 = ASE->getLHS()->getSourceRange();
|
|
|
|
R2 = ASE->getRHS()->getSourceRange();
|
|
|
|
return ASE->getRBracketLoc();
|
|
|
|
}
|
2010-01-22 03:51:34 +08:00
|
|
|
case Expr::CStyleCastExprClass: {
|
|
|
|
const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S);
|
|
|
|
R1 = CSC->getSubExpr()->getSourceRange();
|
|
|
|
return CSC->getLParenLoc();
|
|
|
|
}
|
2010-01-22 06:12:18 +08:00
|
|
|
case Expr::CXXFunctionalCastExprClass: {
|
|
|
|
const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
|
|
|
|
R1 = CE->getSubExpr()->getSourceRange();
|
|
|
|
return CE->getTypeBeginLoc();
|
|
|
|
}
|
2010-01-22 03:44:04 +08:00
|
|
|
case Expr::ImplicitCastExprClass:
|
|
|
|
++sn;
|
|
|
|
goto top;
|
2010-01-21 23:20:48 +08:00
|
|
|
case Stmt::CXXTryStmtClass: {
|
|
|
|
return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
|
|
|
|
}
|
2010-01-21 11:59:47 +08:00
|
|
|
default: ;
|
|
|
|
}
|
2010-01-22 07:15:53 +08:00
|
|
|
R1 = S->getSourceRange();
|
2010-01-21 11:59:47 +08:00
|
|
|
return S->getLocStart();
|
|
|
|
}
|
|
|
|
|
|
|
|
static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live,
|
|
|
|
SourceManager &SM) {
|
|
|
|
std::queue<CFGBlock*> workq;
|
|
|
|
// Prep work queue
|
|
|
|
workq.push(e);
|
2010-01-22 01:21:23 +08:00
|
|
|
SourceRange R1, R2;
|
|
|
|
SourceLocation top = GetUnreachableLoc(*e, R1, R2);
|
2010-01-21 11:59:47 +08:00
|
|
|
bool FromMainFile = false;
|
|
|
|
bool FromSystemHeader = false;
|
|
|
|
bool TopValid = false;
|
|
|
|
if (top.isValid()) {
|
|
|
|
FromMainFile = SM.isFromMainFile(top);
|
|
|
|
FromSystemHeader = SM.isInSystemHeader(top);
|
|
|
|
TopValid = true;
|
|
|
|
}
|
|
|
|
// Solve
|
|
|
|
while (!workq.empty()) {
|
|
|
|
CFGBlock *item = workq.front();
|
|
|
|
workq.pop();
|
2010-01-22 01:21:23 +08:00
|
|
|
SourceLocation c = GetUnreachableLoc(*item, R1, R2);
|
2010-01-21 11:59:47 +08:00
|
|
|
if (c.isValid()
|
|
|
|
&& (!TopValid
|
|
|
|
|| (SM.isFromMainFile(c) && !FromMainFile)
|
|
|
|
|| (FromSystemHeader && !SM.isInSystemHeader(c))
|
|
|
|
|| SM.isBeforeInTranslationUnit(c, top))) {
|
|
|
|
top = c;
|
|
|
|
FromMainFile = SM.isFromMainFile(top);
|
|
|
|
FromSystemHeader = SM.isInSystemHeader(top);
|
|
|
|
}
|
|
|
|
live.set(item->getBlockID());
|
|
|
|
for (CFGBlock::succ_iterator I=item->succ_begin(),
|
|
|
|
E=item->succ_end();
|
|
|
|
I != E;
|
|
|
|
++I) {
|
|
|
|
if ((*I) && !live[(*I)->getBlockID()]) {
|
|
|
|
live.set((*I)->getBlockID());
|
|
|
|
workq.push(*I);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return top;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int LineCmp(const void *p1, const void *p2) {
|
|
|
|
SourceLocation *Line1 = (SourceLocation *)p1;
|
|
|
|
SourceLocation *Line2 = (SourceLocation *)p2;
|
|
|
|
return !(*Line1 < *Line2);
|
|
|
|
}
|
|
|
|
|
2010-01-22 07:49:01 +08:00
|
|
|
namespace {
|
|
|
|
struct ErrLoc {
|
|
|
|
SourceLocation Loc;
|
|
|
|
SourceRange R1;
|
|
|
|
SourceRange R2;
|
|
|
|
ErrLoc(SourceLocation l, SourceRange r1, SourceRange r2)
|
|
|
|
: Loc(l), R1(r1), R2(r2) { }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2010-01-21 11:59:47 +08:00
|
|
|
/// CheckUnreachable - Check for unreachable code.
|
|
|
|
void Sema::CheckUnreachable(AnalysisContext &AC) {
|
|
|
|
unsigned count;
|
|
|
|
// We avoid checking when there are errors, as the CFG won't faithfully match
|
|
|
|
// the user's code.
|
|
|
|
if (getDiagnostics().hasErrorOccurred())
|
|
|
|
return;
|
|
|
|
if (Diags.getDiagnosticLevel(diag::warn_unreachable) == Diagnostic::Ignored)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CFG *cfg = AC.getCFG();
|
|
|
|
if (cfg == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
llvm::BitVector live(cfg->getNumBlockIDs());
|
|
|
|
// Mark all live things first.
|
|
|
|
count = MarkLive(&cfg->getEntry(), live);
|
|
|
|
|
|
|
|
if (count == cfg->getNumBlockIDs())
|
|
|
|
// If there are no dead blocks, we're done.
|
|
|
|
return;
|
|
|
|
|
2010-01-22 01:21:23 +08:00
|
|
|
SourceRange R1, R2;
|
|
|
|
|
2010-01-22 07:49:01 +08:00
|
|
|
llvm::SmallVector<ErrLoc, 24> lines;
|
2010-01-21 23:20:48 +08:00
|
|
|
bool AddEHEdges = AC.getAddEHEdges();
|
2010-01-21 11:59:47 +08:00
|
|
|
// First, give warnings for blocks with no predecessors, as they
|
|
|
|
// can't be part of a loop.
|
|
|
|
for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
|
|
|
|
CFGBlock &b = **I;
|
|
|
|
if (!live[b.getBlockID()]) {
|
|
|
|
if (b.pred_begin() == b.pred_end()) {
|
2010-01-21 23:20:48 +08:00
|
|
|
if (!AddEHEdges && b.getTerminator()
|
|
|
|
&& isa<CXXTryStmt>(b.getTerminator())) {
|
|
|
|
// When not adding EH edges from calls, catch clauses
|
|
|
|
// can otherwise seem dead. Avoid noting them as dead.
|
|
|
|
count += MarkLive(&b, live);
|
|
|
|
continue;
|
|
|
|
}
|
2010-01-22 01:21:23 +08:00
|
|
|
SourceLocation c = GetUnreachableLoc(b, R1, R2);
|
2010-01-21 11:59:47 +08:00
|
|
|
if (!c.isValid()) {
|
|
|
|
// Blocks without a location can't produce a warning, so don't mark
|
|
|
|
// reachable blocks from here as live.
|
|
|
|
live.set(b.getBlockID());
|
|
|
|
++count;
|
|
|
|
continue;
|
|
|
|
}
|
2010-01-22 07:49:01 +08:00
|
|
|
lines.push_back(ErrLoc(c, R1, R2));
|
2010-01-21 11:59:47 +08:00
|
|
|
// Avoid excessive errors by marking everything reachable from here
|
|
|
|
count += MarkLive(&b, live);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count < cfg->getNumBlockIDs()) {
|
|
|
|
// And then give warnings for the tops of loops.
|
|
|
|
for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
|
|
|
|
CFGBlock &b = **I;
|
|
|
|
if (!live[b.getBlockID()])
|
|
|
|
// Avoid excessive errors by marking everything reachable from here
|
2010-01-28 09:04:48 +08:00
|
|
|
lines.push_back(ErrLoc(MarkLiveTop(&b, live,
|
|
|
|
Context.getSourceManager()),
|
|
|
|
SourceRange(), SourceRange()));
|
2010-01-21 11:59:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::array_pod_sort(lines.begin(), lines.end(), LineCmp);
|
2010-01-22 07:49:01 +08:00
|
|
|
for (llvm::SmallVector<ErrLoc, 24>::iterator I = lines.begin(),
|
2010-01-21 11:59:47 +08:00
|
|
|
E = lines.end();
|
|
|
|
I != E;
|
|
|
|
++I)
|
2010-01-22 07:49:01 +08:00
|
|
|
if (I->Loc.isValid())
|
|
|
|
Diag(I->Loc, diag::warn_unreachable) << I->R1 << I->R2;
|
2010-01-21 11:59:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// CheckFallThrough - Check that we don't fall off the end of a
|
|
|
|
/// Statement that should return a value.
|
|
|
|
///
|
|
|
|
/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
|
|
|
|
/// MaybeFallThrough iff we might or might not fall off the end,
|
|
|
|
/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
|
|
|
|
/// return. We assume NeverFallThrough iff we never fall off the end of the
|
|
|
|
/// statement but we may return. We assume that functions not marked noreturn
|
|
|
|
/// will return.
|
|
|
|
Sema::ControlFlowKind Sema::CheckFallThrough(AnalysisContext &AC) {
|
|
|
|
CFG *cfg = AC.getCFG();
|
|
|
|
if (cfg == 0)
|
|
|
|
// FIXME: This should be NeverFallThrough
|
|
|
|
return NeverFallThroughOrReturn;
|
|
|
|
|
2010-01-21 23:20:48 +08:00
|
|
|
// The CFG leaves in dead things, and we don't want the dead code paths to
|
2010-01-21 11:59:47 +08:00
|
|
|
// confuse us, so we mark all live things first.
|
|
|
|
std::queue<CFGBlock*> workq;
|
|
|
|
llvm::BitVector live(cfg->getNumBlockIDs());
|
2010-01-21 23:20:48 +08:00
|
|
|
unsigned count = MarkLive(&cfg->getEntry(), live);
|
|
|
|
|
|
|
|
bool AddEHEdges = AC.getAddEHEdges();
|
|
|
|
if (!AddEHEdges && count != cfg->getNumBlockIDs())
|
|
|
|
// When there are things remaining dead, and we didn't add EH edges
|
|
|
|
// from CallExprs to the catch clauses, we have to go back and
|
|
|
|
// mark them as live.
|
|
|
|
for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
|
|
|
|
CFGBlock &b = **I;
|
|
|
|
if (!live[b.getBlockID()]) {
|
|
|
|
if (b.pred_begin() == b.pred_end()) {
|
|
|
|
if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
|
|
|
|
// When not adding EH edges from calls, catch clauses
|
|
|
|
// can otherwise seem dead. Avoid noting them as dead.
|
|
|
|
count += MarkLive(&b, live);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-01-21 11:59:47 +08:00
|
|
|
|
|
|
|
// Now we know what is live, we check the live precessors of the exit block
|
|
|
|
// and look for fall through paths, being careful to ignore normal returns,
|
|
|
|
// and exceptional paths.
|
|
|
|
bool HasLiveReturn = false;
|
|
|
|
bool HasFakeEdge = false;
|
|
|
|
bool HasPlainEdge = false;
|
|
|
|
bool HasAbnormalEdge = false;
|
|
|
|
for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
|
|
|
|
E = cfg->getExit().pred_end();
|
|
|
|
I != E;
|
|
|
|
++I) {
|
|
|
|
CFGBlock& B = **I;
|
|
|
|
if (!live[B.getBlockID()])
|
|
|
|
continue;
|
|
|
|
if (B.size() == 0) {
|
2010-01-21 23:20:48 +08:00
|
|
|
if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
|
|
|
|
HasAbnormalEdge = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-01-21 11:59:47 +08:00
|
|
|
// A labeled empty statement, or the entry block...
|
|
|
|
HasPlainEdge = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Stmt *S = B[B.size()-1];
|
|
|
|
if (isa<ReturnStmt>(S)) {
|
|
|
|
HasLiveReturn = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (isa<ObjCAtThrowStmt>(S)) {
|
|
|
|
HasFakeEdge = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (isa<CXXThrowExpr>(S)) {
|
|
|
|
HasFakeEdge = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
|
|
|
|
if (AS->isMSAsm()) {
|
|
|
|
HasFakeEdge = true;
|
|
|
|
HasLiveReturn = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isa<CXXTryStmt>(S)) {
|
|
|
|
HasAbnormalEdge = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NoReturnEdge = false;
|
|
|
|
if (CallExpr *C = dyn_cast<CallExpr>(S)) {
|
|
|
|
if (B.succ_begin()[0] != &cfg->getExit()) {
|
|
|
|
HasAbnormalEdge = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Expr *CEE = C->getCallee()->IgnoreParenCasts();
|
|
|
|
if (CEE->getType().getNoReturnAttr()) {
|
|
|
|
NoReturnEdge = true;
|
|
|
|
HasFakeEdge = true;
|
|
|
|
} else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
|
|
|
|
ValueDecl *VD = DRE->getDecl();
|
|
|
|
if (VD->hasAttr<NoReturnAttr>()) {
|
|
|
|
NoReturnEdge = true;
|
|
|
|
HasFakeEdge = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// FIXME: Add noreturn message sends.
|
|
|
|
if (NoReturnEdge == false)
|
|
|
|
HasPlainEdge = true;
|
|
|
|
}
|
|
|
|
if (!HasPlainEdge) {
|
|
|
|
if (HasLiveReturn)
|
|
|
|
return NeverFallThrough;
|
|
|
|
return NeverFallThroughOrReturn;
|
|
|
|
}
|
|
|
|
if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
|
|
|
|
return MaybeFallThrough;
|
|
|
|
// This says AlwaysFallThrough for calls to functions that are not marked
|
|
|
|
// noreturn, that don't return. If people would like this warning to be more
|
|
|
|
// accurate, such functions should be marked as noreturn.
|
|
|
|
return AlwaysFallThrough;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
|
|
|
|
/// function that should return a value. Check that we don't fall off the end
|
|
|
|
/// of a noreturn function. We assume that functions and blocks not marked
|
|
|
|
/// noreturn will return.
|
|
|
|
void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body,
|
|
|
|
AnalysisContext &AC) {
|
|
|
|
// FIXME: Would be nice if we had a better way to control cascading errors,
|
|
|
|
// but for now, avoid them. The problem is that when Parse sees:
|
|
|
|
// int foo() { return a; }
|
|
|
|
// The return is eaten and the Sema code sees just:
|
|
|
|
// int foo() { }
|
|
|
|
// which this code would then warn about.
|
|
|
|
if (getDiagnostics().hasErrorOccurred())
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool ReturnsVoid = false;
|
|
|
|
bool HasNoReturn = false;
|
|
|
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
2010-02-06 13:31:15 +08:00
|
|
|
// For function templates, class templates and member function templates
|
|
|
|
// we'll do the analysis at instantiation time.
|
|
|
|
if (FD->isDependentContext())
|
2010-01-21 11:59:47 +08:00
|
|
|
return;
|
2010-02-06 13:31:15 +08:00
|
|
|
|
2010-01-21 11:59:47 +08:00
|
|
|
if (FD->getResultType()->isVoidType())
|
|
|
|
ReturnsVoid = true;
|
2010-02-06 05:31:56 +08:00
|
|
|
if (FD->hasAttr<NoReturnAttr>() ||
|
|
|
|
FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
|
2010-01-21 11:59:47 +08:00
|
|
|
HasNoReturn = true;
|
|
|
|
} else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
|
|
|
|
if (MD->getResultType()->isVoidType())
|
|
|
|
ReturnsVoid = true;
|
|
|
|
if (MD->hasAttr<NoReturnAttr>())
|
|
|
|
HasNoReturn = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Short circuit for compilation speed.
|
|
|
|
if ((Diags.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function)
|
|
|
|
== Diagnostic::Ignored || ReturnsVoid)
|
|
|
|
&& (Diags.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr)
|
|
|
|
== Diagnostic::Ignored || !HasNoReturn)
|
|
|
|
&& (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
|
|
|
|
== Diagnostic::Ignored || !ReturnsVoid))
|
|
|
|
return;
|
|
|
|
// FIXME: Function try block
|
|
|
|
if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
|
|
|
|
switch (CheckFallThrough(AC)) {
|
|
|
|
case MaybeFallThrough:
|
|
|
|
if (HasNoReturn)
|
|
|
|
Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function);
|
|
|
|
else if (!ReturnsVoid)
|
|
|
|
Diag(Compound->getRBracLoc(),diag::warn_maybe_falloff_nonvoid_function);
|
|
|
|
break;
|
|
|
|
case AlwaysFallThrough:
|
|
|
|
if (HasNoReturn)
|
|
|
|
Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function);
|
|
|
|
else if (!ReturnsVoid)
|
|
|
|
Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function);
|
|
|
|
break;
|
|
|
|
case NeverFallThroughOrReturn:
|
|
|
|
if (ReturnsVoid && !HasNoReturn)
|
|
|
|
Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function);
|
|
|
|
break;
|
|
|
|
case NeverFallThrough:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// CheckFallThroughForBlock - Check that we don't fall off the end of a block
|
|
|
|
/// that should return a value. Check that we don't fall off the end of a
|
|
|
|
/// noreturn block. We assume that functions and blocks not marked noreturn
|
|
|
|
/// will return.
|
|
|
|
void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body,
|
|
|
|
AnalysisContext &AC) {
|
|
|
|
// FIXME: Would be nice if we had a better way to control cascading errors,
|
|
|
|
// but for now, avoid them. The problem is that when Parse sees:
|
|
|
|
// int foo() { return a; }
|
|
|
|
// The return is eaten and the Sema code sees just:
|
|
|
|
// int foo() { }
|
|
|
|
// which this code would then warn about.
|
|
|
|
if (getDiagnostics().hasErrorOccurred())
|
|
|
|
return;
|
|
|
|
bool ReturnsVoid = false;
|
|
|
|
bool HasNoReturn = false;
|
|
|
|
if (const FunctionType *FT =BlockTy->getPointeeType()->getAs<FunctionType>()){
|
|
|
|
if (FT->getResultType()->isVoidType())
|
|
|
|
ReturnsVoid = true;
|
|
|
|
if (FT->getNoReturnAttr())
|
|
|
|
HasNoReturn = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Short circuit for compilation speed.
|
|
|
|
if (ReturnsVoid
|
|
|
|
&& !HasNoReturn
|
|
|
|
&& (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
|
|
|
|
== Diagnostic::Ignored || !ReturnsVoid))
|
|
|
|
return;
|
|
|
|
// FIXME: Funtion try block
|
|
|
|
if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
|
|
|
|
switch (CheckFallThrough(AC)) {
|
|
|
|
case MaybeFallThrough:
|
|
|
|
if (HasNoReturn)
|
|
|
|
Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr);
|
|
|
|
else if (!ReturnsVoid)
|
|
|
|
Diag(Compound->getRBracLoc(), diag::err_maybe_falloff_nonvoid_block);
|
|
|
|
break;
|
|
|
|
case AlwaysFallThrough:
|
|
|
|
if (HasNoReturn)
|
|
|
|
Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr);
|
|
|
|
else if (!ReturnsVoid)
|
|
|
|
Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block);
|
|
|
|
break;
|
|
|
|
case NeverFallThroughOrReturn:
|
|
|
|
if (ReturnsVoid)
|
|
|
|
Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block);
|
|
|
|
break;
|
|
|
|
case NeverFallThrough:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// CheckParmsForFunctionDef - Check that the parameters of the given
|
|
|
|
/// function are appropriate for the definition of a function. This
|
|
|
|
/// takes care of any checks that cannot be performed on the
|
|
|
|
/// declaration itself, e.g., that the types of each of the function
|
|
|
|
/// parameters are complete.
|
|
|
|
bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
|
|
|
|
bool HasInvalidParm = false;
|
|
|
|
for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
|
|
|
|
ParmVarDecl *Param = FD->getParamDecl(p);
|
|
|
|
|
|
|
|
// C99 6.7.5.3p4: the parameters in a parameter type list in a
|
|
|
|
// function declarator that is part of a function definition of
|
|
|
|
// that function shall not have incomplete type.
|
|
|
|
//
|
|
|
|
// This is also C++ [dcl.fct]p6.
|
|
|
|
if (!Param->isInvalidDecl() &&
|
|
|
|
RequireCompleteType(Param->getLocation(), Param->getType(),
|
|
|
|
diag::err_typecheck_decl_incomplete_type)) {
|
|
|
|
Param->setInvalidDecl();
|
|
|
|
HasInvalidParm = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// C99 6.9.1p5: If the declarator includes a parameter type list, the
|
|
|
|
// declaration of each parameter shall include an identifier.
|
|
|
|
if (Param->getIdentifier() == 0 &&
|
|
|
|
!Param->isImplicit() &&
|
|
|
|
!getLangOptions().CPlusPlus)
|
|
|
|
Diag(Param->getLocation(), diag::err_parameter_name_omitted);
|
2010-02-01 13:02:49 +08:00
|
|
|
|
|
|
|
// C99 6.7.5.3p12:
|
|
|
|
// If the function declarator is not part of a definition of that
|
|
|
|
// function, parameters may have incomplete type and may use the [*]
|
|
|
|
// notation in their sequences of declarator specifiers to specify
|
|
|
|
// variable length array types.
|
|
|
|
QualType PType = Param->getOriginalType();
|
|
|
|
if (const ArrayType *AT = Context.getAsArrayType(PType)) {
|
|
|
|
if (AT->getSizeModifier() == ArrayType::Star) {
|
|
|
|
// FIXME: This diagnosic should point the the '[*]' if source-location
|
|
|
|
// information is added for it.
|
|
|
|
Diag(Param->getLocation(), diag::err_array_star_in_function_definition);
|
|
|
|
}
|
|
|
|
}
|
2010-02-02 16:45:54 +08:00
|
|
|
|
2010-02-02 17:10:11 +08:00
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
if (const RecordType *RT = Param->getType()->getAs<RecordType>())
|
|
|
|
FinalizeVarWithDestructor(Param, RT);
|
2010-01-21 11:59:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return HasInvalidParm;
|
|
|
|
}
|