Optimize Declarator to avoid malloc/free traffic for the argument list of a
function DeclaratorChunk in common cases.  This uses a fixed array in 
Declarator when it is small enough for the first function declarator chunk
in a declarator.

This eliminates all malloc/free traffic from DeclaratorChunk::getFunction
when running on Cocoa.h except for five functions: signal/bsd_signal/sigset,
which have multiple Function DeclChunk's, and 
CFUUIDCreateWithBytes/CFUUIDGetConstantUUIDWithBytes, which take more than
16 arguments.

This patch was pair programmed with Steve.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62599 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 4459c80..83bf36c 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -14,6 +14,7 @@
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/STLExtras.h"
 using namespace clang;
 
 
@@ -23,6 +24,43 @@
 }
 
 
+/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
+/// "TheDeclarator" is the declarator that this will be added to.
+DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
+                                             ParamInfo *ArgInfo,
+                                             unsigned NumArgs,
+                                             unsigned TypeQuals,
+                                             SourceLocation Loc,
+                                             Declarator &TheDeclarator) {
+  DeclaratorChunk I;
+  I.Kind             = Function;
+  I.Loc              = Loc;
+  I.Fun.hasPrototype = hasProto;
+  I.Fun.isVariadic   = isVariadic;
+  I.Fun.DeleteArgInfo = false;
+  I.Fun.TypeQuals    = TypeQuals;
+  I.Fun.NumArgs      = NumArgs;
+  I.Fun.ArgInfo      = 0;
+  
+  // new[] an argument array if needed.
+  if (NumArgs) {
+    // If the 'InlineParams' in Declarator is unused and big enough, put our
+    // parameter list there (in an effort to avoid new/delete traffic).  If it
+    // is already used (consider a function returning a function pointer) or too
+    // small (function taking too many arguments), go to the heap.
+    if (!TheDeclarator.InlineParamsUsed && 
+        NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
+      I.Fun.ArgInfo = TheDeclarator.InlineParams;
+      I.Fun.DeleteArgInfo = false;
+      TheDeclarator.InlineParamsUsed = true;
+    } else {
+      I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
+      I.Fun.DeleteArgInfo = true;
+    }
+    memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
+  }
+  return I;
+}
 
 /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
 ///
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 456acbe..bf92278 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1854,7 +1854,7 @@
                                                /*variadic*/ false,
                                                /*arglist*/ 0, 0,
                                                DS.getTypeQualifiers(),
-                                               LParenLoc));
+                                               LParenLoc, D));
     return;
   } 
   
@@ -2013,7 +2013,7 @@
   D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
                                              &ParamInfo[0], ParamInfo.size(),
                                              DS.getTypeQualifiers(),
-                                             LParenLoc));
+                                             LParenLoc, D));
 }
 
 /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
@@ -2080,7 +2080,7 @@
   // has no prototype.
   D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
                                              &ParamInfo[0], ParamInfo.size(),
-                                             /*TypeQuals*/0, LParenLoc));
+                                             /*TypeQuals*/0, LParenLoc, D));
   
   // If we have the closing ')', eat it and we're done.
   MatchRHSPunctuation(tok::r_paren, LParenLoc);
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index dc95c38..3851855 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1222,7 +1222,8 @@
   } else {
     // Otherwise, pretend we saw (void).
     ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
-                                                       0, 0, 0, CaretLoc));
+                                                       0, 0, 0, CaretLoc,
+                                                       ParamInfo));
   }
 
   // Inform sema that we are starting a block.