class ScopedDecl;
class Expr;
class InitListExpr;
+ class CallExpr;
class VarDecl;
class ParmVarDecl;
class TypedefDecl;
ExprTy **ArgExprs, unsigned NumArgs);
private:
// UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
- // functions and arrays to their respective pointers (C99 6.3.2.1).
- void UsualUnaryConversions(Expr *&expr);
+ // functions and arrays to their respective pointers (C99 6.3.2.1).
+ Expr *UsualUnaryConversions(Expr *&expr);
// DefaultFunctionArrayConversion - converts functions and arrays
// to their respective pointers (C99 6.3.2.1).
// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
// do not have a prototype. Integer promotions are performed on each
// argument, and arguments that have type float are promoted to double.
- void DefaultArgumentPromotion(Expr *&expr);
+ void DefaultArgumentPromotion(Expr *&Expr);
// UsualArithmeticConversions - performs the UsualUnaryConversions on it's
// operands and then handles various conversions that are common to binary
//===--------------------------------------------------------------------===//
// Extra semantic analysis beyond the C type system
- private:
-
- bool CheckFunctionCall(Expr *Fn, SourceLocation RParenLoc,
- FunctionDecl *FDecl,
- Expr** Args, unsigned NumArgsInCall);
-
- void CheckPrintfArguments(Expr *Fn, SourceLocation RParenLoc,
- bool HasVAListArg, FunctionDecl *FDecl,
- unsigned format_idx, Expr** Args,
- unsigned NumArgsInCall);
-
+private:
+ bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
+ bool CheckBuiltinCFStringArgument(Expr* Arg);
+ bool SemaBuiltinVAStart(CallExpr *TheCall);
+ bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
+ void CheckPrintfArguments(CallExpr *TheCall,
+ bool HasVAListArg, unsigned format_idx);
void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc);
-
-
- bool CheckBuiltinCFStringArgument(Expr* Arg);
- bool SemaBuiltinVAStart(Expr *Fn, Expr** Args, unsigned NumArgs);
- bool SemaBuiltinUnorderedCompare(Expr *Fn, Expr** Args, unsigned NumArgs,
- SourceLocation RParenLoc);
-
void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
};
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "SemaUtil.h"
-
using namespace clang;
/// CheckFunctionCall - Check a direct function call for various correctness
/// and safety properties not strictly enforced by the C type system.
bool
-Sema::CheckFunctionCall(Expr *Fn, SourceLocation RParenLoc,
- FunctionDecl *FDecl, Expr** Args, unsigned NumArgs) {
+Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
// Get the IdentifierInfo* for the called function.
IdentifierInfo *FnInfo = FDecl->getIdentifier();
switch (FnInfo->getBuiltinID()) {
case Builtin::BI__builtin___CFStringMakeConstantString:
- assert(NumArgs == 1 &&
+ assert(TheCall->getNumArgs() == 1 &&
"Wrong # arguments to builtin CFStringMakeConstantString");
- return CheckBuiltinCFStringArgument(Args[0]);
+ return CheckBuiltinCFStringArgument(TheCall->getArg(0));
case Builtin::BI__builtin_va_start:
- return SemaBuiltinVAStart(Fn, Args, NumArgs);
+ return SemaBuiltinVAStart(TheCall);
case Builtin::BI__builtin_isgreater:
case Builtin::BI__builtin_isgreaterequal:
case Builtin::BI__builtin_islessequal:
case Builtin::BI__builtin_islessgreater:
case Builtin::BI__builtin_isunordered:
- return SemaBuiltinUnorderedCompare(Fn, Args, NumArgs, RParenLoc);
+ return SemaBuiltinUnorderedCompare(TheCall);
}
// Search the KnownFunctionIDs for the identifier.
case id_vprintf: format_idx = 0; HasVAListArg = true; break;
}
- CheckPrintfArguments(Fn, RParenLoc, HasVAListArg,
- FDecl, format_idx, Args, NumArgs);
+ CheckPrintfArguments(TheCall, HasVAListArg, format_idx);
}
return false;
/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity.
/// Emit an error and return true on failure, return false on success.
-bool Sema::SemaBuiltinVAStart(Expr *Fn, Expr** Args, unsigned NumArgs) {
- if (NumArgs > 2) {
- Diag(Args[2]->getLocStart(),
+bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
+ Expr *Fn = TheCall->getCallee();
+ if (TheCall->getNumArgs() > 2) {
+ Diag(TheCall->getArg(2)->getLocStart(),
diag::err_typecheck_call_too_many_args, Fn->getSourceRange(),
- SourceRange(Args[2]->getLocStart(), Args[NumArgs-1]->getLocEnd()));
+ SourceRange(TheCall->getArg(2)->getLocStart(),
+ (*(TheCall->arg_end()-1))->getLocEnd()));
return true;
}
// Verify that the second argument to the builtin is the last argument of the
// current function or method.
bool SecondArgIsLastNamedArgument = false;
- if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Args[1])) {
+ if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(TheCall->getArg(1))) {
if (ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
// FIXME: This isn't correct for methods (results in bogus warning).
// Get the last formal in the current function.
}
if (!SecondArgIsLastNamedArgument)
- Diag(Args[1]->getLocStart(),
+ Diag(TheCall->getArg(1)->getLocStart(),
diag::warn_second_parameter_of_va_start_not_last_named_argument);
return false;
}
/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and
/// friends. This is declared to take (...), so we have to check everything.
-bool Sema::SemaBuiltinUnorderedCompare(Expr *Fn, Expr** Args, unsigned NumArgs,
- SourceLocation RParenLoc) {
- if (NumArgs < 2)
- return Diag(RParenLoc, diag::err_typecheck_call_too_few_args);
- if (NumArgs > 2)
- return Diag(Args[2]->getLocStart(), diag::err_typecheck_call_too_many_args,
- SourceRange(Args[2]->getLocStart(),
- Args[NumArgs-1]->getLocEnd()));
-
- Expr *OrigArg0 = Args[0];
- Expr *OrigArg1 = Args[1];
+bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
+ if (TheCall->getNumArgs() < 2)
+ return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args);
+ if (TheCall->getNumArgs() > 2)
+ return Diag(TheCall->getArg(2)->getLocStart(),
+ diag::err_typecheck_call_too_many_args,
+ SourceRange(TheCall->getArg(2)->getLocStart(),
+ (*(TheCall->arg_end()-1))->getLocEnd()));
+
+ Expr *OrigArg0 = TheCall->getArg(0);
+ Expr *OrigArg1 = TheCall->getArg(1);
// Do standard promotions between the two arguments, returning their common
// type.
- QualType Res = UsualArithmeticConversions(Args[0], Args[1], false);
+ QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false);
// If the common type isn't a real floating type, then the arguments were
// invalid for this operation.
if (!Res->isRealFloatingType())
- return Diag(Args[0]->getLocStart(),
+ return Diag(OrigArg0->getLocStart(),
diag::err_typecheck_call_invalid_ordered_compare,
OrigArg0->getType().getAsString(),
OrigArg1->getType().getAsString(),
- SourceRange(Args[0]->getLocStart(), Args[1]->getLocEnd()));
+ SourceRange(OrigArg0->getLocStart(), OrigArg1->getLocEnd()));
return false;
}
///
/// For now, we ONLY do (1), (3), (5), (6), (7), and (8).
void
-Sema::CheckPrintfArguments(Expr *Fn, SourceLocation RParenLoc,
- bool HasVAListArg, FunctionDecl *FDecl,
- unsigned format_idx, Expr** Args,
- unsigned NumArgs) {
+Sema::CheckPrintfArguments(CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx) {
+ Expr *Fn = TheCall->getCallee();
+
// CHECK: printf-like function is called with no format string.
- if (format_idx >= NumArgs) {
- Diag(RParenLoc, diag::warn_printf_missing_format_string,
+ if (format_idx >= TheCall->getNumArgs()) {
+ Diag(TheCall->getRParenLoc(), diag::warn_printf_missing_format_string,
Fn->getSourceRange());
return;
}
- Expr *OrigFormatExpr = Args[format_idx];
+ Expr *OrigFormatExpr = TheCall->getArg(format_idx);
// FIXME: This should go in a helper.
while (1) {
if (ParenExpr *PE = dyn_cast<ParenExpr>(OrigFormatExpr))
if (isa<ParmVarDecl>(DR->getDecl()))
return;
- Diag(Args[format_idx]->getLocStart(), diag::warn_printf_not_string_constant,
- Fn->getSourceRange());
-
+ Diag(TheCall->getArg(format_idx)->getLocStart(),
+ diag::warn_printf_not_string_constant, Fn->getSourceRange());
return;
}
// CHECK: is the format string a wide literal?
if (FExpr->isWide()) {
- Diag(Args[format_idx]->getLocStart(),
- diag::warn_printf_format_string_is_wide_literal,
- Fn->getSourceRange());
+ Diag(FExpr->getLocStart(),
+ diag::warn_printf_format_string_is_wide_literal, Fn->getSourceRange());
return;
}
const unsigned StrLen = FExpr->getByteLength();
if (StrLen == 0) {
- Diag(Args[format_idx]->getLocStart(),
- diag::warn_printf_empty_format_string, Fn->getSourceRange());
+ Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string,
+ Fn->getSourceRange());
return;
}
// string. This can only be determined for non vprintf-like
// functions. For those functions, this value is 1 (the sole
// va_arg argument).
- unsigned numDataArgs = NumArgs-(format_idx+1);
+ unsigned numDataArgs = TheCall->getNumArgs()-(format_idx+1);
// Inspect the format string.
unsigned StrIdx = 0;
// a '%' character that starts a new format conversion.
unsigned LastConversionIdx = 0;
- for ( ; StrIdx < StrLen ; ++StrIdx ) {
+ for (; StrIdx < StrLen; ++StrIdx) {
// Is the number of detected conversion conversions greater than
// the number of matching data arguments? If so, stop.
if (!HasVAListArg && numConversions > numDataArgs) break;
// Handle "\0"
- if(Str[StrIdx] == '\0' ) {
+ if (Str[StrIdx] == '\0') {
// The string returned by getStrData() is not null-terminated,
// so the presence of a null character is likely an error.
-
- SourceLocation Loc =
- PP.AdvanceToTokenCharacter(Args[format_idx]->getLocStart(),StrIdx+1);
+ SourceLocation Loc = FExpr->getLocStart();
+ Loc = PP.AdvanceToTokenCharacter(Loc, StrIdx+1);
Diag(Loc, diag::warn_printf_format_string_contains_null_char,
Fn->getSourceRange());
-
return;
}
// Seen '%'. Now processing a format conversion.
switch (Str[StrIdx]) {
- // Handle dynamic precision or width specifier.
+ // Handle dynamic precision or width specifier.
case '*': {
++numConversions;
if (!HasVAListArg && numConversions > numDataArgs) {
- SourceLocation Loc =
- PP.AdvanceToTokenCharacter(Args[format_idx]->getLocStart(),
- StrIdx+1);
+ SourceLocation Loc = FExpr->getLocStart();
+ Loc = PP.AdvanceToTokenCharacter(Loc, StrIdx+1);
if (Str[StrIdx-1] == '.')
Diag(Loc, diag::warn_printf_asterisk_precision_missing_arg,
Fn->getSourceRange());
else
Diag(Loc, diag::warn_printf_asterisk_width_missing_arg,
- Fn->getSourceRange());
+ Fn->getSourceRange());
// Don't do any more checking. We'll just emit spurious errors.
return;
}
// Perform type checking on width/precision specifier.
- Expr* E = Args[format_idx+numConversions];
- QualType T = E->getType().getCanonicalType();
- if (BuiltinType *BT = dyn_cast<BuiltinType>(T))
- if (BT->getKind() == BuiltinType::Int)
- break;
+ Expr *E = TheCall->getArg(format_idx+numConversions);
+ if (const BuiltinType *BT = E->getType()->getAsBuiltinType())
+ if (BT->getKind() == BuiltinType::Int)
+ break;
SourceLocation Loc =
- PP.AdvanceToTokenCharacter(Args[format_idx]->getLocStart(),
- StrIdx+1);
+ PP.AdvanceToTokenCharacter(FExpr->getLocStart(), StrIdx+1);
if (Str[StrIdx-1] == '.')
Diag(Loc, diag::warn_printf_asterisk_precision_wrong_type,
- T.getAsString(), E->getSourceRange());
+ E->getType().getAsString(), E->getSourceRange());
else
Diag(Loc, diag::warn_printf_asterisk_width_wrong_type,
- T.getAsString(), E->getSourceRange());
+ E->getType().getAsString(), E->getSourceRange());
break;
}
case 'n': {
++numConversions;
CurrentState = state_OrdChr;
- SourceLocation Loc =
- PP.AdvanceToTokenCharacter(Args[format_idx]->getLocStart(),
- LastConversionIdx+1);
+ SourceLocation Loc = PP.AdvanceToTokenCharacter(FExpr->getLocStart(),
+ LastConversionIdx+1);
Diag(Loc, diag::warn_printf_write_back, Fn->getSourceRange());
break;
CurrentState = state_OrdChr;
else {
// Issue a warning: invalid format conversion.
- SourceLocation Loc =
- PP.AdvanceToTokenCharacter(Args[format_idx]->getLocStart(),
- LastConversionIdx+1);
+ SourceLocation Loc = PP.AdvanceToTokenCharacter(FExpr->getLocStart(),
+ LastConversionIdx+1);
Diag(Loc, diag::warn_printf_invalid_conversion,
std::string(Str+LastConversionIdx, Str+StrIdx),
if (CurrentState == state_Conversion) {
// Issue a warning: invalid format conversion.
- SourceLocation Loc =
- PP.AdvanceToTokenCharacter(Args[format_idx]->getLocStart(),
- LastConversionIdx+1);
+ SourceLocation Loc = PP.AdvanceToTokenCharacter(FExpr->getLocStart(),
+ LastConversionIdx+1);
Diag(Loc, diag::warn_printf_invalid_conversion,
std::string(Str+LastConversionIdx,
// CHECK: Does the number of format conversions exceed the number
// of data arguments?
if (numConversions > numDataArgs) {
- SourceLocation Loc =
- PP.AdvanceToTokenCharacter(Args[format_idx]->getLocStart(),
- LastConversionIdx);
+ SourceLocation Loc = PP.AdvanceToTokenCharacter(FExpr->getLocStart(),
+ LastConversionIdx);
Diag(Loc, diag::warn_printf_insufficient_data_args,
Fn->getSourceRange());
// CHECK: Does the number of data arguments exceed the number of
// format conversions in the format string?
else if (numConversions < numDataArgs)
- Diag(Args[format_idx+numConversions+1]->getLocStart(),
+ Diag(TheCall->getArg(format_idx+numConversions+1)->getLocStart(),
diag::warn_printf_too_many_data_args, Fn->getSourceRange());
}
}
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
/// locations.
Action::ExprResult Sema::
ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc,
- ExprTy **args, unsigned NumArgsInCall,
+ ExprTy **args, unsigned NumArgs,
SourceLocation *CommaLocs, SourceLocation RParenLoc) {
Expr *Fn = static_cast<Expr *>(fn);
Expr **Args = reinterpret_cast<Expr**>(args);
assert(Fn && "no function call expression");
- UsualUnaryConversions(Fn);
- QualType funcType = Fn->getType();
-
+ // Make the call expr early, before semantic checks. This guarantees cleanup
+ // of arguments and function on error.
+ llvm::OwningPtr<CallExpr> TheCall(new CallExpr(Fn, Args, NumArgs,
+ Context.BoolTy, RParenLoc));
+
+ // Promote the function operand.
+ TheCall->setCallee(UsualUnaryConversions(Fn));
+
// C99 6.5.2.2p1 - "The expression that denotes the called function shall have
// type pointer to function".
- const PointerType *PT = funcType->getAsPointerType();
+ const PointerType *PT = Fn->getType()->getAsPointerType();
if (PT == 0)
return Diag(Fn->getLocStart(), diag::err_typecheck_call_not_function,
SourceRange(Fn->getLocStart(), RParenLoc));
-
- const FunctionType *funcT = PT->getPointeeType()->getAsFunctionType();
- if (funcT == 0)
+ const FunctionType *FuncT = PT->getPointeeType()->getAsFunctionType();
+ if (FuncT == 0)
return Diag(Fn->getLocStart(), diag::err_typecheck_call_not_function,
SourceRange(Fn->getLocStart(), RParenLoc));
+
+ // We know the result type of the call, set it.
+ TheCall->setType(FuncT->getResultType());
- // If a prototype isn't declared, the parser implicitly defines a func decl
- QualType resultType = funcT->getResultType();
-
- if (const FunctionTypeProto *proto = dyn_cast<FunctionTypeProto>(funcT)) {
+ if (const FunctionTypeProto *Proto = dyn_cast<FunctionTypeProto>(FuncT)) {
// C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
// assignment, to the types of the corresponding parameter, ...
+ unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumArgsToCheck = NumArgs;
- unsigned NumArgsInProto = proto->getNumArgs();
- unsigned NumArgsToCheck = NumArgsInCall;
+ // If too few arguments are available, don't make the call.
+ if (NumArgs < NumArgsInProto)
+ return Diag(RParenLoc, diag::err_typecheck_call_too_few_args,
+ Fn->getSourceRange());
- if (NumArgsInCall < NumArgsInProto)
- Diag(RParenLoc, diag::err_typecheck_call_too_few_args,
- Fn->getSourceRange());
- else if (NumArgsInCall > NumArgsInProto) {
- if (!proto->isVariadic()) {
+ // If too many are passed and not variadic, error on the extras and drop
+ // them.
+ if (NumArgs > NumArgsInProto) {
+ if (!Proto->isVariadic()) {
Diag(Args[NumArgsInProto]->getLocStart(),
diag::err_typecheck_call_too_many_args, Fn->getSourceRange(),
SourceRange(Args[NumArgsInProto]->getLocStart(),
- Args[NumArgsInCall-1]->getLocEnd()));
+ Args[NumArgs-1]->getLocEnd()));
+ // This deletes the extra arguments.
+ TheCall->setNumArgs(NumArgsInProto);
}
NumArgsToCheck = NumArgsInProto;
}
+
// Continue to check argument types (even if we have too few/many args).
- for (unsigned i = 0; i < NumArgsToCheck; i++) {
- Expr *argExpr = Args[i];
- assert(argExpr && "ActOnCallExpr(): missing argument expression");
-
- QualType lhsType = proto->getArgType(i);
- QualType rhsType = argExpr->getType();
+ for (unsigned i = 0; i != NumArgsToCheck; i++) {
+ Expr *Arg = Args[i];
+ QualType LHSType = Proto->getArgType(i);
+ QualType RHSType = Arg->getType();
// If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
- if (const ArrayType *ary = lhsType->getAsArrayType())
- lhsType = Context.getPointerType(ary->getElementType());
- else if (lhsType->isFunctionType())
- lhsType = Context.getPointerType(lhsType);
-
- AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType,
- argExpr);
- if (Args[i] != argExpr) // The expression was converted.
- Args[i] = argExpr; // Make sure we store the converted expression.
- SourceLocation l = argExpr->getLocStart();
-
- // decode the result (notice that AST's are still created for extensions).
- switch (result) {
+ if (const ArrayType *AT = LHSType->getAsArrayType())
+ LHSType = Context.getPointerType(AT->getElementType());
+ else if (LHSType->isFunctionType())
+ LHSType = Context.getPointerType(LHSType);
+
+ // Compute implicit casts from the operand to the formal argument type.
+ AssignmentCheckResult Result =
+ CheckSingleAssignmentConstraints(LHSType, Arg);
+ TheCall->setArg(i, Arg);
+
+ // Decode the result (notice that AST's are still created for extensions).
+ SourceLocation Loc = Arg->getLocStart();
+ switch (Result) {
case Compatible:
break;
case PointerFromInt:
- Diag(l, diag::ext_typecheck_passing_pointer_int,
- lhsType.getAsString(), rhsType.getAsString(),
- Fn->getSourceRange(), argExpr->getSourceRange());
+ Diag(Loc, diag::ext_typecheck_passing_pointer_int,
+ LHSType.getAsString(), RHSType.getAsString(),
+ Fn->getSourceRange(), Arg->getSourceRange());
break;
case IntFromPointer:
- Diag(l, diag::ext_typecheck_passing_pointer_int,
- lhsType.getAsString(), rhsType.getAsString(),
- Fn->getSourceRange(), argExpr->getSourceRange());
+ Diag(Loc, diag::ext_typecheck_passing_pointer_int,
+ LHSType.getAsString(), RHSType.getAsString(),
+ Fn->getSourceRange(), Arg->getSourceRange());
break;
case IncompatiblePointer:
- Diag(l, diag::ext_typecheck_passing_incompatible_pointer,
- rhsType.getAsString(), lhsType.getAsString(),
- Fn->getSourceRange(), argExpr->getSourceRange());
+ Diag(Loc, diag::ext_typecheck_passing_incompatible_pointer,
+ RHSType.getAsString(), LHSType.getAsString(),
+ Fn->getSourceRange(), Arg->getSourceRange());
break;
case CompatiblePointerDiscardsQualifiers:
- Diag(l, diag::ext_typecheck_passing_discards_qualifiers,
- rhsType.getAsString(), lhsType.getAsString(),
- Fn->getSourceRange(), argExpr->getSourceRange());
+ Diag(Loc, diag::ext_typecheck_passing_discards_qualifiers,
+ RHSType.getAsString(), LHSType.getAsString(),
+ Fn->getSourceRange(), Arg->getSourceRange());
break;
case Incompatible:
- return Diag(l, diag::err_typecheck_passing_incompatible,
- rhsType.getAsString(), lhsType.getAsString(),
- Fn->getSourceRange(), argExpr->getSourceRange());
+ return Diag(Loc, diag::err_typecheck_passing_incompatible,
+ RHSType.getAsString(), LHSType.getAsString(),
+ Fn->getSourceRange(), Arg->getSourceRange());
}
}
- if (NumArgsInCall > NumArgsInProto && proto->isVariadic()) {
+
+ // If this is a variadic call, handle args passed through "...".
+ if (Proto->isVariadic()) {
// Promote the arguments (C99 6.5.2.2p7).
- for (unsigned i = NumArgsInProto; i < NumArgsInCall; i++) {
- Expr *argExpr = Args[i];
- assert(argExpr && "ActOnCallExpr(): missing argument expression");
-
- DefaultArgumentPromotion(argExpr);
- if (Args[i] != argExpr) // The expression was converted.
- Args[i] = argExpr; // Make sure we store the converted expression.
+ for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
+ Expr *Arg = Args[i];
+ DefaultArgumentPromotion(Arg);
+ TheCall->setArg(i, Arg);
}
- } else if (NumArgsInCall != NumArgsInProto && !proto->isVariadic()) {
- // Even if the types checked, bail if the number of arguments don't match.
- return true;
}
- } else if (isa<FunctionTypeNoProto>(funcT)) {
+ } else {
+ assert(isa<FunctionTypeNoProto>(FuncT) && "Unknown FunctionType!");
+
// Promote the arguments (C99 6.5.2.2p6).
- for (unsigned i = 0; i < NumArgsInCall; i++) {
- Expr *argExpr = Args[i];
- assert(argExpr && "ActOnCallExpr(): missing argument expression");
-
- DefaultArgumentPromotion(argExpr);
- if (Args[i] != argExpr) // The expression was converted.
- Args[i] = argExpr; // Make sure we store the converted expression.
+ for (unsigned i = 0; i != NumArgs; i++) {
+ Expr *Arg = Args[i];
+ DefaultArgumentPromotion(Arg);
+ TheCall->setArg(i, Arg);
}
}
+
// Do special checking on direct calls to functions.
if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()))
if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()))
- if (CheckFunctionCall(Fn, RParenLoc, FDecl, Args, NumArgsInCall)) {
- // Function rejected, delete sub-ast's.
- delete Fn;
- for (unsigned i = 0; i != NumArgsInCall; ++i)
- delete Args[i];
+ if (CheckFunctionCall(FDecl, TheCall.get()))
return true;
- }
- return new CallExpr(Fn, Args, NumArgsInCall, resultType, RParenLoc);
+ return TheCall.take();
}
Action::ExprResult Sema::
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
/// do not have a prototype. Integer promotions are performed on each
/// argument, and arguments that have type float are promoted to double.
-void Sema::DefaultArgumentPromotion(Expr *&expr) {
- QualType t = expr->getType();
- assert(!t.isNull() && "DefaultArgumentPromotion - missing type");
-
- if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
- promoteExprToType(expr, Context.IntTy);
- if (t == Context.FloatTy)
- promoteExprToType(expr, Context.DoubleTy);
+void Sema::DefaultArgumentPromotion(Expr *&Expr) {
+ QualType Ty = Expr->getType();
+ assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type");
+
+ if (Ty->isPromotableIntegerType()) // C99 6.3.1.1p2
+ promoteExprToType(Expr, Context.IntTy);
+ if (Ty == Context.FloatTy)
+ promoteExprToType(Expr, Context.DoubleTy);
}
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
/// sometimes surpressed. For example, the array->pointer conversion doesn't
/// apply if the array is an argument to the sizeof or address (&) operators.
/// In these instances, this routine should *not* be called.
-void Sema::UsualUnaryConversions(Expr *&expr) {
- QualType t = expr->getType();
- assert(!t.isNull() && "UsualUnaryConversions - missing type");
+Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
+ QualType Ty = Expr->getType();
+ assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
- if (const ReferenceType *ref = t->getAsReferenceType()) {
- promoteExprToType(expr, ref->getReferenceeType()); // C++ [expr]
- t = expr->getType();
+ if (const ReferenceType *Ref = Ty->getAsReferenceType()) {
+ promoteExprToType(Expr, Ref->getReferenceeType()); // C++ [expr]
+ Ty = Expr->getType();
}
- if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
- promoteExprToType(expr, Context.IntTy);
+ if (Ty->isPromotableIntegerType()) // C99 6.3.1.1p2
+ promoteExprToType(Expr, Context.IntTy);
else
- DefaultFunctionArrayConversion(expr);
+ DefaultFunctionArrayConversion(Expr);
+
+ return Expr;
}
/// UsualArithmeticConversions - Performs various conversions that are common to