[cfe-commits] r45380 - in /cfe/trunk/Sema: Sema.h SemaChecking.cpp SemaExpr.cpp

Chris Lattner sabre at nondot.org
Thu Dec 27 21:30:00 PST 2007


Author: lattner
Date: Thu Dec 27 23:29:59 2007
New Revision: 45380

URL: http://llvm.org/viewvc/llvm-project?rev=45380&view=rev
Log:
Change Sema::ActOnCallExpr to construct the CallExpr early and put it into
and OwningPtr instead of constructing only after all of sema is done.  This
has a couple of effects:
1. it fixes memory leaks from all the error cases in sema
2. it simplifies the code significantly.

The cost of this is that the error case now new's and delete's an expr where
it did not before, but we don't care about the perf of the error case.

Modified:
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaChecking.cpp
    cfe/trunk/Sema/SemaExpr.cpp

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=45380&r1=45379&r2=45380&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Thu Dec 27 23:29:59 2007
@@ -34,6 +34,7 @@
   class ScopedDecl;
   class Expr;
   class InitListExpr;
+  class CallExpr;
   class VarDecl;
   class ParmVarDecl;
   class TypedefDecl;
@@ -582,8 +583,8 @@
     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). 
@@ -592,7 +593,7 @@
   // 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
@@ -712,26 +713,15 @@
   
   //===--------------------------------------------------------------------===//
   // 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);
 };
 

Modified: cfe/trunk/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaChecking.cpp?rev=45380&r1=45379&r2=45380&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/Sema/SemaChecking.cpp Thu Dec 27 23:29:59 2007
@@ -26,25 +26,23 @@
 #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:
@@ -52,7 +50,7 @@
   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.
@@ -81,8 +79,7 @@
     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;
@@ -134,11 +131,13 @@
 
 /// 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;
   }
   
@@ -158,7 +157,7 @@
   // 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.
@@ -172,37 +171,37 @@
   }
   
   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()));
+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 = Args[0];
-  Expr *OrigArg1 = Args[1];
+  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;
 }
@@ -255,18 +254,18 @@
 ///
 /// 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))
@@ -310,17 +309,15 @@
           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;
   }
 
@@ -331,8 +328,8 @@
   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;
   }
 
@@ -351,7 +348,7 @@
   //  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;
@@ -360,23 +357,21 @@
   //  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;
     }
     
@@ -391,44 +386,41 @@
 
     // 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;
       }
@@ -468,9 +460,8 @@
       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;
@@ -486,9 +477,8 @@
           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),
@@ -511,9 +501,8 @@
 
   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,
@@ -526,9 +515,8 @@
     // 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());
@@ -536,7 +524,7 @@
     // 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());
   }
 }

Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=45380&r1=45379&r2=45380&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Thu Dec 27 23:29:59 2007
@@ -24,6 +24,7 @@
 #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;
@@ -558,137 +559,136 @@
 /// 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 (NumArgsInCall < NumArgsInProto)
-      Diag(RParenLoc, diag::err_typecheck_call_too_few_args,
-           Fn->getSourceRange());
-    else if (NumArgsInCall > NumArgsInProto) {
-      if (!proto->isVariadic()) {
+    // 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 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::
@@ -892,14 +892,14 @@
 /// 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).
@@ -922,18 +922,20 @@
 /// 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");
-  
-  if (const ReferenceType *ref = t->getAsReferenceType()) {
-    promoteExprToType(expr, ref->getReferenceeType()); // C++ [expr]
-    t = expr->getType();
+Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
+  QualType Ty = Expr->getType();
+  assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
+  
+  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





More information about the cfe-commits mailing list