diff options
author | Steve Naroff <snaroff@apple.com> | 2007-08-28 23:30:39 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2007-08-28 23:30:39 +0000 |
commit | b291ab60474e8f02f5d1245f77d3af31bcd4821c (patch) | |
tree | ca461ffeb3fe251f50f9913cc34663f930744aed | |
parent | 7269f2d6cbe8c876aa5b007c35e4a3c3fed72cbd (diff) |
Implement default argument promotions (for old-style function calls and variable argument lists).
[dylan:~/llvm/tools/clang] admin% cat x.c
int printf(const char *, ...);
int oldschool();
void foo() {
float f;
short i;
printf("foo %f", 1.0f);
oldschool(f,i);
}
[dylan:~/llvm/tools/clang] admin% ../../Debug/bin/clang x.c -parse-ast-dump
int printf(char const *, ...);
int oldschool();
void foo()
(CompoundStmt 0x3105f00
(DeclStmt 0x3105ba0
0x3105ce0 "float f")
(DeclStmt 0x3105c90
0x3105d10 "short i")
(CallExpr 0x3105df0 'int'
(ImplicitCastExpr 0x3105dc0 'int (*)(char const *, ...)'
(DeclRefExpr 0x3105c20 'int (char const *, ...)' Decl='printf' 0x3105bd0))
(ImplicitCastExpr 0x3105dd0 'char const *'
(StringLiteral 0x3105d60 'char *' "foo %f"))
(ImplicitCastExpr 0x3105de0 'double'
(FloatingLiteral 0x3105d80 'float' 1.000000)))
(CallExpr 0x3105ed0 'int'
(ImplicitCastExpr 0x3105ea0 'int (*)()'
(DeclRefExpr 0x3105e20 'int ()' Decl='oldschool' 0x3105c40))
(ImplicitCastExpr 0x3105eb0 'double'
(DeclRefExpr 0x3105e40 'float' Decl='f' 0x3105ce0))
(ImplicitCastExpr 0x3105ec0 'int'
(DeclRefExpr 0x3105e60 'short' Decl='i' 0x3105d10))))
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41558 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | Sema/Sema.h | 5 | ||||
-rw-r--r-- | Sema/SemaExpr.cpp | 39 |
2 files changed, 41 insertions, 3 deletions
diff --git a/Sema/Sema.h b/Sema/Sema.h index 5c391516da..2c496a76cd 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -344,6 +344,11 @@ private: // to their respective pointers (C99 6.3.2.1). void DefaultFunctionArrayConversion(Expr *&expr); + // 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); + // UsualArithmeticConversions - performs the UsualUnaryConversions on it's // operands and then handles various conversions that are common to binary // operators (C99 6.3.1.8). If both operands aren't arithmetic, this diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index eb7daf18c7..9208db26a8 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -585,11 +585,31 @@ ParseCallExpr(ExprTy *fn, SourceLocation LParenLoc, Fn->getSourceRange(), argExpr->getSourceRange()); } } - // Even if the types checked, bail if we had the wrong number of arguments. - if (NumArgsInCall != NumArgsInProto && !proto->isVariadic()) + if (NumArgsInCall > NumArgsInProto && proto->isVariadic()) { + // Promote the arguments (C99 6.5.2.2p7). + for (unsigned i = NumArgsInProto; i < NumArgsInCall; i++) { + Expr *argExpr = Args[i]; + assert(argExpr && "ParseCallExpr(): missing argument expression"); + + DefaultArgumentPromotion(argExpr); + if (Args[i] != argExpr) // The expression was converted. + Args[i] = argExpr; // Make sure we store the converted expression. + } + } 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)) { + // Promote the arguments (C99 6.5.2.2p6). + for (unsigned i = 0; i < NumArgsInCall; i++) { + Expr *argExpr = Args[i]; + assert(argExpr && "ParseCallExpr(): missing argument expression"); + + DefaultArgumentPromotion(argExpr); + if (Args[i] != argExpr) // The expression was converted. + Args[i] = argExpr; // Make sure we store the converted expression. + } } - // Do special checking on direct calls to functions. if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn)) if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr())) @@ -746,6 +766,19 @@ static void promoteExprToType(Expr *&expr, QualType type) { return; } +/// 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); +} + /// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4). void Sema::DefaultFunctionArrayConversion(Expr *&e) { QualType t = e->getType(); |