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"
|
|
|
|
#include "clang/AST/ASTContext.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"
|
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"
|
2009-05-20 09:55:10 +08:00
|
|
|
#include <limits>
|
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;
|
|
|
|
switch (Context.getTypeSize(ValType)/8) {
|
|
|
|
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) {
|
|
|
|
const VarDecl *Def = 0;
|
|
|
|
if (const Expr *Init = VD->getDefinition(Def))
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-03-21 05:35:28 +08:00
|
|
|
void Sema::CheckPrintfString(const StringLiteral *FExpr,
|
|
|
|
const Expr *OrigFormatExpr,
|
|
|
|
const CallExpr *TheCall, bool HasVAListArg,
|
|
|
|
unsigned format_idx, unsigned firstDataArg) {
|
|
|
|
|
|
|
|
const ObjCStringLiteral *ObjCFExpr =
|
|
|
|
dyn_cast<ObjCStringLiteral>(OrigFormatExpr);
|
2007-08-15 01:39:48 +08:00
|
|
|
|
|
|
|
// CHECK: is the format string a wide literal?
|
|
|
|
if (FExpr->isWide()) {
|
2007-12-28 13:29:59 +08:00
|
|
|
Diag(FExpr->getLocStart(),
|
2008-11-19 13:27:50 +08:00
|
|
|
diag::warn_printf_format_string_is_wide_literal)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
2007-08-15 01:39:48 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Str - The format string. NOTE: this is NOT null-terminated!
|
2009-04-29 12:12:34 +08:00
|
|
|
const char *Str = FExpr->getStrData();
|
2007-08-15 01:39:48 +08:00
|
|
|
|
|
|
|
// CHECK: empty format string?
|
2009-04-29 12:12:34 +08:00
|
|
|
unsigned StrLen = FExpr->getByteLength();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-15 01:39:48 +08:00
|
|
|
if (StrLen == 0) {
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
2007-08-15 01:39:48 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We process the format string using a binary state machine. The
|
|
|
|
// current state is stored in CurrentState.
|
|
|
|
enum {
|
|
|
|
state_OrdChr,
|
|
|
|
state_Conversion
|
|
|
|
} CurrentState = state_OrdChr;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-15 01:39:48 +08:00
|
|
|
// numConversions - The number of conversions seen so far. This is
|
|
|
|
// incremented as we traverse the format string.
|
|
|
|
unsigned numConversions = 0;
|
|
|
|
|
|
|
|
// numDataArgs - The number of data arguments after the format
|
|
|
|
// string. This can only be determined for non vprintf-like
|
|
|
|
// functions. For those functions, this value is 1 (the sole
|
|
|
|
// va_arg argument).
|
2009-02-15 02:57:46 +08:00
|
|
|
unsigned numDataArgs = TheCall->getNumArgs()-firstDataArg;
|
2007-08-15 01:39:48 +08:00
|
|
|
|
|
|
|
// Inspect the format string.
|
|
|
|
unsigned StrIdx = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-15 01:39:48 +08:00
|
|
|
// LastConversionIdx - Index within the format string where we last saw
|
|
|
|
// a '%' character that starts a new format conversion.
|
|
|
|
unsigned LastConversionIdx = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:29:59 +08:00
|
|
|
for (; StrIdx < StrLen; ++StrIdx) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-15 01:39:48 +08:00
|
|
|
// Is the number of detected conversion conversions greater than
|
|
|
|
// the number of matching data arguments? If so, stop.
|
|
|
|
if (!HasVAListArg && numConversions > numDataArgs) break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-15 01:39:48 +08:00
|
|
|
// Handle "\0"
|
2007-12-28 13:29:59 +08:00
|
|
|
if (Str[StrIdx] == '\0') {
|
2007-08-15 01:39:48 +08:00
|
|
|
// The string returned by getStrData() is not null-terminated,
|
|
|
|
// so the presence of a null character is likely an error.
|
2009-02-19 01:49:48 +08:00
|
|
|
Diag(getLocationOfStringLiteralByte(FExpr, StrIdx),
|
2008-11-19 13:27:50 +08:00
|
|
|
diag::warn_printf_format_string_contains_null_char)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
2007-08-15 01:39:48 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-15 01:39:48 +08:00
|
|
|
// Ordinary characters (not processing a format conversion).
|
|
|
|
if (CurrentState == state_OrdChr) {
|
|
|
|
if (Str[StrIdx] == '%') {
|
|
|
|
CurrentState = state_Conversion;
|
|
|
|
LastConversionIdx = StrIdx;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Seen '%'. Now processing a format conversion.
|
|
|
|
switch (Str[StrIdx]) {
|
2009-09-09 23:08:12 +08:00
|
|
|
// Handle dynamic precision or width specifier.
|
2007-12-28 13:31:15 +08:00
|
|
|
case '*': {
|
|
|
|
++numConversions;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-14 00:06:05 +08:00
|
|
|
if (!HasVAListArg) {
|
|
|
|
if (numConversions > numDataArgs) {
|
|
|
|
SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx);
|
|
|
|
|
|
|
|
if (Str[StrIdx-1] == '.')
|
|
|
|
Diag(Loc, diag::warn_printf_asterisk_precision_missing_arg)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
|
|
|
else
|
|
|
|
Diag(Loc, diag::warn_printf_asterisk_width_missing_arg)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-14 00:06:05 +08:00
|
|
|
// Don't do any more checking. We'll just emit spurious errors.
|
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-14 00:06:05 +08:00
|
|
|
// Perform type checking on width/precision specifier.
|
|
|
|
const Expr *E = TheCall->getArg(format_idx+numConversions);
|
2009-09-22 07:43:11 +08:00
|
|
|
if (const BuiltinType *BT = E->getType()->getAs<BuiltinType>())
|
2009-05-14 00:06:05 +08:00
|
|
|
if (BT->getKind() == BuiltinType::Int)
|
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-19 01:49:48 +08:00
|
|
|
SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-13 04:51:52 +08:00
|
|
|
if (Str[StrIdx-1] == '.')
|
2009-05-14 00:06:05 +08:00
|
|
|
Diag(Loc, diag::warn_printf_asterisk_precision_wrong_type)
|
|
|
|
<< E->getType() << E->getSourceRange();
|
2007-10-13 04:51:52 +08:00
|
|
|
else
|
2009-05-14 00:06:05 +08:00
|
|
|
Diag(Loc, diag::warn_printf_asterisk_width_wrong_type)
|
|
|
|
<< E->getType() << E->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
break;
|
2007-10-13 04:51:52 +08:00
|
|
|
}
|
2007-12-28 13:31:15 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
// Characters which can terminate a format conversion
|
|
|
|
// (e.g. "%d"). Characters that specify length modifiers or
|
|
|
|
// other flags are handled by the default case below.
|
|
|
|
//
|
2009-09-09 23:08:12 +08:00
|
|
|
// FIXME: additional checks will go into the following cases.
|
2007-12-28 13:31:15 +08:00
|
|
|
case 'i':
|
|
|
|
case 'd':
|
2009-09-09 23:08:12 +08:00
|
|
|
case 'o':
|
|
|
|
case 'u':
|
2007-12-28 13:31:15 +08:00
|
|
|
case 'x':
|
|
|
|
case 'X':
|
|
|
|
case 'D':
|
|
|
|
case 'O':
|
|
|
|
case 'U':
|
|
|
|
case 'e':
|
|
|
|
case 'E':
|
|
|
|
case 'f':
|
|
|
|
case 'F':
|
|
|
|
case 'g':
|
|
|
|
case 'G':
|
|
|
|
case 'a':
|
|
|
|
case 'A':
|
|
|
|
case 'c':
|
|
|
|
case 'C':
|
|
|
|
case 'S':
|
|
|
|
case 's':
|
2009-09-09 23:08:12 +08:00
|
|
|
case 'p':
|
2007-12-28 13:31:15 +08:00
|
|
|
++numConversions;
|
|
|
|
CurrentState = state_OrdChr;
|
|
|
|
break;
|
2007-08-15 01:39:48 +08:00
|
|
|
|
2009-06-02 16:36:19 +08:00
|
|
|
case 'm':
|
|
|
|
// FIXME: Warn in situations where this isn't supported!
|
|
|
|
CurrentState = state_OrdChr;
|
|
|
|
break;
|
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
// CHECK: Are we using "%n"? Issue a warning.
|
|
|
|
case 'n': {
|
|
|
|
++numConversions;
|
|
|
|
CurrentState = state_OrdChr;
|
2009-02-19 01:49:48 +08:00
|
|
|
SourceLocation Loc = getLocationOfStringLiteralByte(FExpr,
|
|
|
|
LastConversionIdx);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(Loc, diag::warn_printf_write_back)<<OrigFormatExpr->getSourceRange();
|
2007-12-28 13:31:15 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-06-17 02:00:42 +08:00
|
|
|
// Handle "%@"
|
|
|
|
case '@':
|
|
|
|
// %@ is allowed in ObjC format strings only.
|
2009-09-09 23:08:12 +08:00
|
|
|
if (ObjCFExpr != NULL)
|
|
|
|
CurrentState = state_OrdChr;
|
2008-06-17 02:00:42 +08:00
|
|
|
else {
|
|
|
|
// Issue a warning: invalid format conversion.
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation Loc =
|
2009-02-19 01:49:48 +08:00
|
|
|
getLocationOfStringLiteralByte(FExpr, LastConversionIdx);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-20 14:06:08 +08:00
|
|
|
Diag(Loc, diag::warn_printf_invalid_conversion)
|
|
|
|
<< std::string(Str+LastConversionIdx,
|
|
|
|
Str+std::min(LastConversionIdx+2, StrLen))
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
2008-06-17 02:00:42 +08:00
|
|
|
}
|
|
|
|
++numConversions;
|
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
// Handle "%%"
|
|
|
|
case '%':
|
|
|
|
// Sanity check: Was the first "%" character the previous one?
|
|
|
|
// If not, we will assume that we have a malformed format
|
|
|
|
// conversion, and that the current "%" character is the start
|
|
|
|
// of a new conversion.
|
|
|
|
if (StrIdx - LastConversionIdx == 1)
|
2009-09-09 23:08:12 +08:00
|
|
|
CurrentState = state_OrdChr;
|
2007-12-28 13:31:15 +08:00
|
|
|
else {
|
|
|
|
// Issue a warning: invalid format conversion.
|
2009-02-19 01:49:48 +08:00
|
|
|
SourceLocation Loc =
|
|
|
|
getLocationOfStringLiteralByte(FExpr, LastConversionIdx);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-20 14:06:08 +08:00
|
|
|
Diag(Loc, diag::warn_printf_invalid_conversion)
|
|
|
|
<< std::string(Str+LastConversionIdx, Str+StrIdx)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
// This conversion is broken. Advance to the next format
|
|
|
|
// conversion.
|
|
|
|
LastConversionIdx = StrIdx;
|
|
|
|
++numConversions;
|
2007-08-15 01:39:48 +08:00
|
|
|
}
|
2007-12-28 13:31:15 +08:00
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-28 13:31:15 +08:00
|
|
|
default:
|
|
|
|
// This case catches all other characters: flags, widths, etc.
|
|
|
|
// We should eventually process those as well.
|
|
|
|
break;
|
2007-08-15 01:39:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CurrentState == state_Conversion) {
|
|
|
|
// Issue a warning: invalid format conversion.
|
2009-02-19 01:49:48 +08:00
|
|
|
SourceLocation Loc =
|
|
|
|
getLocationOfStringLiteralByte(FExpr, LastConversionIdx);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-20 14:06:08 +08:00
|
|
|
Diag(Loc, diag::warn_printf_invalid_conversion)
|
|
|
|
<< std::string(Str+LastConversionIdx,
|
|
|
|
Str+std::min(LastConversionIdx+2, StrLen))
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
2007-08-15 01:39:48 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-15 01:39:48 +08:00
|
|
|
if (!HasVAListArg) {
|
|
|
|
// CHECK: Does the number of format conversions exceed the number
|
|
|
|
// of data arguments?
|
|
|
|
if (numConversions > numDataArgs) {
|
2009-02-19 01:49:48 +08:00
|
|
|
SourceLocation Loc =
|
|
|
|
getLocationOfStringLiteralByte(FExpr, LastConversionIdx);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(Loc, diag::warn_printf_insufficient_data_args)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
2007-08-15 01:39:48 +08:00
|
|
|
}
|
|
|
|
// CHECK: Does the number of data arguments exceed the number of
|
|
|
|
// format conversions in the format string?
|
|
|
|
else if (numConversions < numDataArgs)
|
2007-12-28 13:29:59 +08:00
|
|
|
Diag(TheCall->getArg(format_idx+numConversions+1)->getLocStart(),
|
2008-11-19 13:27:50 +08:00
|
|
|
diag::warn_printf_too_many_data_args)
|
|
|
|
<< OrigFormatExpr->getSourceRange();
|
2007-08-15 01:39:48 +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
|
|
|
|
|
|
|
//===--- CHECK: Comparison of signed and unsigned int (-Wsign-compare) ----===//
|
|
|
|
|
|
|
|
/// Returns true if we can prove that the result of the given
|
|
|
|
/// integral expression will not have its sign bit set.
|
|
|
|
static bool IsSignBitProvablyZero(ASTContext &Context, Expr *E) {
|
|
|
|
E = E->IgnoreParens();
|
|
|
|
|
|
|
|
llvm::APSInt value;
|
|
|
|
if (E->isIntegerConstantExpr(value, Context))
|
|
|
|
return value.isNonNegative();
|
|
|
|
|
|
|
|
if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E))
|
|
|
|
return IsSignBitProvablyZero(Context, CO->getLHS()) &&
|
|
|
|
IsSignBitProvablyZero(Context, CO->getRHS());
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-01-05 07:31:57 +08:00
|
|
|
/// Retrieves the width and signedness of the given integer type,
|
|
|
|
/// or returns false if it is not an integer type.
|
|
|
|
///
|
|
|
|
/// \param T must be canonical
|
|
|
|
static bool getIntProperties(ASTContext &C, const Type *T,
|
|
|
|
unsigned &BitWidth, bool &Signed) {
|
|
|
|
assert(T->isCanonicalUnqualified());
|
|
|
|
|
|
|
|
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 BuiltinType *BT = dyn_cast<BuiltinType>(T)) {
|
|
|
|
if (!BT->isInteger()) return false;
|
|
|
|
|
|
|
|
BitWidth = C.getIntWidth(QualType(T, 0));
|
|
|
|
Signed = BT->isSignedInteger();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks whether the given value will have the same value if it it
|
|
|
|
/// is truncated to the given width, then extended back to the
|
|
|
|
/// original width.
|
|
|
|
static bool IsSameIntAfterCast(const llvm::APSInt &value,
|
|
|
|
unsigned TargetWidth) {
|
|
|
|
unsigned SourceWidth = value.getBitWidth();
|
|
|
|
llvm::APSInt truncated = value;
|
|
|
|
truncated.trunc(TargetWidth);
|
|
|
|
truncated.extend(SourceWidth);
|
|
|
|
return (truncated == value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks whether the given value will have the same value if it
|
|
|
|
/// is truncated to the given width, then extended back to the original
|
|
|
|
/// width.
|
|
|
|
///
|
|
|
|
/// The value might be a vector or a complex.
|
|
|
|
static bool IsSameIntAfterCast(const APValue &value, unsigned TargetWidth) {
|
|
|
|
if (value.isInt())
|
|
|
|
return IsSameIntAfterCast(value.getInt(), TargetWidth);
|
|
|
|
|
|
|
|
if (value.isVector()) {
|
|
|
|
for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
|
|
|
|
if (!IsSameIntAfterCast(value.getVectorElt(i), TargetWidth))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value.isComplexInt()) {
|
|
|
|
return IsSameIntAfterCast(value.getComplexIntReal(), TargetWidth) &&
|
|
|
|
IsSameIntAfterCast(value.getComplexIntImag(), TargetWidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This can happen with lossless casts to intptr_t of "based" lvalues.
|
|
|
|
// Assume it might use arbitrary bits.
|
|
|
|
assert(value.isLValue());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Checks whether the given value, which currently has the given
|
|
|
|
/// source semantics, has the same value when coerced through the
|
|
|
|
/// target semantics.
|
|
|
|
static 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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).
|
|
|
|
static 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));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Determines if it's reasonable for the given expression to be truncated
|
|
|
|
/// down to the given integer width.
|
|
|
|
/// * Boolean expressions are automatically white-listed.
|
|
|
|
/// * Arithmetic operations on implicitly-promoted operands of the
|
|
|
|
/// target width or less are okay --- not because the results are
|
|
|
|
/// actually guaranteed to fit within the width, but because the
|
|
|
|
/// user is effectively pretending that the operations are closed
|
|
|
|
/// within the implicitly-promoted type.
|
|
|
|
static bool IsExprValueWithinWidth(ASTContext &C, Expr *E, unsigned Width) {
|
|
|
|
E = E->IgnoreParens();
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
{
|
|
|
|
const Type *ETy = E->getType()->getCanonicalTypeInternal().getTypePtr();
|
|
|
|
unsigned EWidth;
|
|
|
|
bool ESigned;
|
|
|
|
|
|
|
|
if (!getIntProperties(C, ETy, EWidth, ESigned))
|
|
|
|
assert(0 && "expression not of integer type");
|
|
|
|
|
|
|
|
// The caller should never let this happen.
|
|
|
|
assert(EWidth > Width && "called on expr whose type is too small");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Strip implicit casts off.
|
|
|
|
while (isa<ImplicitCastExpr>(E)) {
|
|
|
|
E = cast<ImplicitCastExpr>(E)->getSubExpr();
|
|
|
|
|
|
|
|
const Type *ETy = E->getType()->getCanonicalTypeInternal().getTypePtr();
|
|
|
|
|
|
|
|
unsigned EWidth;
|
|
|
|
bool ESigned;
|
|
|
|
if (!getIntProperties(C, ETy, EWidth, ESigned))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (EWidth <= Width)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
|
|
|
|
switch (BO->getOpcode()) {
|
|
|
|
|
|
|
|
// Boolean-valued operations are white-listed.
|
|
|
|
case BinaryOperator::LAnd:
|
|
|
|
case BinaryOperator::LOr:
|
|
|
|
case BinaryOperator::LT:
|
|
|
|
case BinaryOperator::GT:
|
|
|
|
case BinaryOperator::LE:
|
|
|
|
case BinaryOperator::GE:
|
|
|
|
case BinaryOperator::EQ:
|
|
|
|
case BinaryOperator::NE:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Operations with opaque sources are black-listed.
|
|
|
|
case BinaryOperator::PtrMemD:
|
|
|
|
case BinaryOperator::PtrMemI:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Left shift gets black-listed based on a judgement call.
|
|
|
|
case BinaryOperator::Shl:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Various special cases.
|
|
|
|
case BinaryOperator::Shr:
|
|
|
|
return IsExprValueWithinWidth(C, BO->getLHS(), Width);
|
|
|
|
case BinaryOperator::Comma:
|
|
|
|
return IsExprValueWithinWidth(C, BO->getRHS(), Width);
|
|
|
|
case BinaryOperator::Sub:
|
|
|
|
if (BO->getLHS()->getType()->isPointerType())
|
|
|
|
return false;
|
|
|
|
// fallthrough
|
|
|
|
|
|
|
|
// Any other operator is okay if the operands are
|
|
|
|
// promoted from expressions of appropriate size.
|
|
|
|
default:
|
|
|
|
return IsExprValueWithinWidth(C, BO->getLHS(), Width) &&
|
|
|
|
IsExprValueWithinWidth(C, BO->getRHS(), Width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
|
|
|
|
switch (UO->getOpcode()) {
|
|
|
|
// Boolean-valued operations are white-listed.
|
|
|
|
case UnaryOperator::LNot:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Operations with opaque sources are black-listed.
|
|
|
|
case UnaryOperator::Deref:
|
|
|
|
case UnaryOperator::AddrOf: // should be impossible
|
|
|
|
return false;
|
|
|
|
|
|
|
|
case UnaryOperator::OffsetOf:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return IsExprValueWithinWidth(C, UO->getSubExpr(), Width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't diagnose if the expression is an integer constant
|
|
|
|
// whose value in the target type is the same as it was
|
|
|
|
// in the original type.
|
|
|
|
Expr::EvalResult result;
|
|
|
|
if (E->Evaluate(result, C))
|
|
|
|
if (IsSameIntAfterCast(result.Val, Width))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
QualType lt = lex->getType(), rt = rex->getType();
|
|
|
|
|
|
|
|
// Only warn if both operands are integral.
|
|
|
|
if (!lt->isIntegerType() || !rt->isIntegerType())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If either expression is value-dependent, don't warn. We'll get another
|
|
|
|
// chance at instantiation time.
|
|
|
|
if (lex->isValueDependent() || rex->isValueDependent())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// The rule is that the signed operand becomes unsigned, so isolate the
|
|
|
|
// signed operand.
|
|
|
|
Expr *signedOperand, *unsignedOperand;
|
|
|
|
if (lt->isSignedIntegerType()) {
|
|
|
|
if (rt->isSignedIntegerType()) return;
|
|
|
|
signedOperand = lex;
|
|
|
|
unsignedOperand = rex;
|
|
|
|
} else {
|
|
|
|
if (!rt->isSignedIntegerType()) return;
|
|
|
|
signedOperand = rex;
|
|
|
|
unsignedOperand = lex;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
if (Context.getIntWidth(signedOperand->getType()) >
|
|
|
|
Context.getIntWidth(unsignedOperand->getType()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If the value is a non-negative integer constant, then the
|
|
|
|
// signed->unsigned conversion won't change it.
|
|
|
|
if (IsSignBitProvablyZero(Context, signedOperand))
|
|
|
|
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.
|
|
|
|
if (Equality && IsSignBitProvablyZero(Context, unsignedOperand))
|
|
|
|
return;
|
|
|
|
|
|
|
|
Diag(OpLoc, PD)
|
|
|
|
<< lex->getType() << rex->getType()
|
|
|
|
<< lex->getSourceRange() << rex->getSourceRange();
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned SourceWidth, TargetWidth;
|
|
|
|
bool SourceSigned, TargetSigned;
|
|
|
|
|
|
|
|
if (!getIntProperties(Context, Source, SourceWidth, SourceSigned) ||
|
|
|
|
!getIntProperties(Context, Target, TargetWidth, TargetSigned))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (SourceWidth > TargetWidth) {
|
|
|
|
if (IsExprValueWithinWidth(Context, E, TargetWidth))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// People want to build with -Wshorten-64-to-32 and not -Wconversion
|
|
|
|
// and by god we'll let them.
|
|
|
|
if (SourceWidth == 64 && TargetWidth == 32)
|
|
|
|
return DiagnoseImpCast(*this, E, T, diag::warn_impcast_integer_64_32);
|
|
|
|
return DiagnoseImpCast(*this, E, T, diag::warn_impcast_integer_precision);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|