Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 97302)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -1362,6 +1362,7 @@
                                DirectDeclParseFunction DirectDeclParser);
   void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true,
                                  bool CXX0XAttributesAllowed = true);
+  void ParsePostIdentifierDeclarator(Declarator &D);
   void ParseDirectDeclarator(Declarator &D);
   void ParseParenDeclarator(Declarator &D);
   void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
Index: include/clang/Parse/DeclSpec.h
===================================================================
--- include/clang/Parse/DeclSpec.h	(revision 97302)
+++ include/clang/Parse/DeclSpec.h	(working copy)
@@ -718,7 +718,8 @@
 /// This is intended to be a small value object.
 struct DeclaratorChunk {
   enum {
-    Pointer, Reference, Array, Function, BlockPointer, MemberPointer
+    Pointer, Reference, Array, Function, BlockPointer, MemberPointer,
+    GroupingParentheses
   } Kind;
 
   /// Loc - The place where this type was defined.
@@ -899,24 +900,33 @@
     }
   };
 
+  struct GroupingParensTypeInfo {
+    AttributeList *AttrList;
+    void destroy() {
+      delete AttrList;
+    }
+  };
+
   union {
-    PointerTypeInfo       Ptr;
-    ReferenceTypeInfo     Ref;
-    ArrayTypeInfo         Arr;
-    FunctionTypeInfo      Fun;
-    BlockPointerTypeInfo  Cls;
-    MemberPointerTypeInfo Mem;
+    PointerTypeInfo        Ptr;
+    ReferenceTypeInfo      Ref;
+    ArrayTypeInfo          Arr;
+    FunctionTypeInfo       Fun;
+    BlockPointerTypeInfo   Cls;
+    MemberPointerTypeInfo  Mem;
+    GroupingParensTypeInfo Par;
   };
 
   void destroy() {
     switch (Kind) {
     default: assert(0 && "Unknown decl type!");
-    case DeclaratorChunk::Function:      return Fun.destroy();
-    case DeclaratorChunk::Pointer:       return Ptr.destroy();
-    case DeclaratorChunk::BlockPointer:  return Cls.destroy();
-    case DeclaratorChunk::Reference:     return Ref.destroy();
-    case DeclaratorChunk::Array:         return Arr.destroy();
-    case DeclaratorChunk::MemberPointer: return Mem.destroy();
+    case DeclaratorChunk::Function:            return Fun.destroy();
+    case DeclaratorChunk::Pointer:             return Ptr.destroy();
+    case DeclaratorChunk::BlockPointer:        return Cls.destroy();
+    case DeclaratorChunk::Reference:           return Ref.destroy();
+    case DeclaratorChunk::Array:               return Arr.destroy();
+    case DeclaratorChunk::MemberPointer:       return Mem.destroy();
+    case DeclaratorChunk::GroupingParentheses: return Par.destroy();
     }
   }
 
@@ -925,12 +935,13 @@
   const AttributeList *getAttrs() const {
     switch (Kind) {
     default: assert(0 && "Unknown declarator kind!");
-    case Pointer:       return Ptr.AttrList;
-    case Reference:     return Ref.AttrList;
-    case MemberPointer: return Mem.AttrList;
-    case Array:         return 0;
-    case Function:      return 0;
-    case BlockPointer:  return Cls.AttrList;
+    case Pointer:             return Ptr.AttrList;
+    case Reference:           return Ref.AttrList;
+    case MemberPointer:       return Mem.AttrList;
+    case Array:               return 0;
+    case Function:            return 0;
+    case BlockPointer:        return Cls.AttrList;
+    case GroupingParentheses: return Par.AttrList;
     }
   }
 
@@ -1014,6 +1025,15 @@
     new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS);
     return I;
   }
+
+  static DeclaratorChunk getGroupingParentheses(SourceLocation Loc,
+                                                AttributeList *AL) {
+    DeclaratorChunk I;
+    I.Kind         = GroupingParentheses;
+    I.Loc          = Loc;
+    I.Par.AttrList = AL;
+    return I;
+  }
 };
 
 /// Declarator - Information about one declarator, including the parsed type
Index: tools/scan-build/ccc-analyzer
===================================================================
--- tools/scan-build/ccc-analyzer	(revision 97302)
+++ tools/scan-build/ccc-analyzer	(working copy)
@@ -339,6 +339,8 @@
 my %CompilerLinkerOptionMap = (
   '-isysroot' => 1,
   '-arch' => 1,
+  '-m32' => 0,
+  '-m64' => 0,
   '-v' => 0,
   '-fpascal-strings' => 0,
   '-mmacosx-version-min' => 0, # This is really a 1 argument, but always has '='
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 97302)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -70,6 +70,7 @@
 
 typedef std::pair<const AttributeList*,QualType> DelayedAttribute;
 typedef llvm::SmallVectorImpl<DelayedAttribute> DelayedAttributeSet;
+typedef llvm::SmallVectorImpl<const AttributeList*> GroupingParensAttributeSet;
 
 static void ProcessTypeAttributeList(Sema &S, QualType &Type,
                                      bool IsDeclSpec,
@@ -96,6 +97,15 @@
   Attrs.clear();
 }
 
+static void ProcessDelayedGroupingParensAttrs(Sema &S, QualType &Type,
+                                           GroupingParensAttributeSet &Attrs) {
+  llvm::SmallVector<DelayedAttribute,4> DelayedFnAttrs;
+  for (GroupingParensAttributeSet::iterator I = Attrs.begin(),
+         E = Attrs.end(); I != E; ++I)
+    ProcessTypeAttributeList(S, Type, false, *I, DelayedFnAttrs);
+  DiagnoseDelayedFnAttrs(S, DelayedFnAttrs);
+}
+
 /// \brief Convert the specified declspec to the appropriate type
 /// object.
 /// \param D  the declarator containing the declaration specifier.
@@ -1006,6 +1016,8 @@
     Name = D.getIdentifier();
 
   llvm::SmallVector<DelayedAttribute,4> FnAttrsFromPreviousChunk;
+  llvm::SmallVector<const AttributeList*,4> GroupingParensAttrs;
+  bool IsFunction = D.isFunctionDeclarator();
 
   // Walk the DeclTypeInfo, building the recursive type as we go.
   // DeclTypeInfos are ordered from the identifier out, which is
@@ -1232,8 +1244,7 @@
 
       // For GCC compatibility, we allow attributes that apply only to
       // function types to be placed on a function's return type
-      // instead (as long as that type doesn't happen to be function
-      // or function-pointer itself).
+      // instead.
       ProcessDelayedFnAttrs(*this, T, FnAttrsFromPreviousChunk);
 
       break;
@@ -1287,6 +1298,16 @@
         D.setInvalidType(true);
       }
       break;
+    case DeclaratorChunk::GroupingParentheses:
+      // This is a special type of chunk used to mark grouping parentheses.
+      // Its purpose here is to hold attributes, so we can apply them to
+      // the right type. The rule is simple: If it's a function, apply it to
+      // the return type (which we just now built up), else delay until we
+      // build up the whole type.
+      if (!IsFunction) {
+        GroupingParensAttrs.push_back(DeclType.getAttrs());
+        continue;
+      }
     }
 
     if (T.isNull()) {
@@ -1333,6 +1354,10 @@
   // declaration-specifiers.
   ProcessDelayedFnAttrs(*this, T, FnAttrsFromDeclSpec);
 
+  // Process any attributes we might have delayed from any grouping
+  // parentheses.
+  ProcessDelayedGroupingParensAttrs(*this, T, GroupingParensAttrs);
+
   // If there were any type attributes applied to the decl itself, not
   // the type, apply them to the result type.  But don't do this for
   // block-literal expressions, which are parsed wierdly.
@@ -1538,7 +1563,11 @@
   UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
 
   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
-    DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL);
+    DeclaratorChunk Chunk = D.getTypeObject(i);
+    // Skip GroupingParentheses chunks: they don't contain any useful type
+    // information.
+    if (Chunk.Kind == DeclaratorChunk::GroupingParentheses) continue;
+    DeclaratorLocFiller(Chunk).Visit(CurrTL);
     CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
   }
   
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 97302)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -2489,6 +2489,36 @@
   }
 }
 
+void Parser::ParsePostIdentifierDeclarator(Declarator &D) {
+  // Don't parse attributes unless we have an identifier.
+  if (D.getIdentifier() && getLang().CPlusPlus0x
+   && isCXX0XAttributeSpecifier(true)) {
+    SourceLocation AttrEndLoc;
+    CXX0XAttributeList Attr = ParseCXX0XAttributes();
+    D.AddAttributes(Attr.AttrList, AttrEndLoc);
+  }
+
+  while (1) {
+    if (Tok.is(tok::l_paren)) {
+      // The paren may be part of a C++ direct initializer, eg. "int x(1);".
+      // In such a case, check if we actually have a function declarator; if it
+      // is not, the declarator has been fully parsed.
+      if (getLang().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) {
+        // When not in file scope, warn for ambiguous function declarators, just
+        // in case the author intended it as a variable definition.
+        bool warnIfAmbiguous = D.getContext() != Declarator::FileContext;
+        if (!isCXXFunctionDeclarator(warnIfAmbiguous))
+          break;
+      }
+      ParseFunctionDeclarator(ConsumeParen(), D);
+    } else if (Tok.is(tok::l_square)) {
+      ParseBracketDeclarator(D);
+    } else {
+      break;
+    }
+  }
+}
+
 /// ParseDirectDeclarator
 ///       direct-declarator: [C99 6.7.5]
 /// [C99]   identifier
@@ -2611,33 +2641,7 @@
   assert(D.isPastIdentifier() &&
          "Haven't past the location of the identifier yet?");
 
-  // Don't parse attributes unless we have an identifier.
-  if (D.getIdentifier() && getLang().CPlusPlus0x
-   && isCXX0XAttributeSpecifier(true)) {
-    SourceLocation AttrEndLoc;
-    CXX0XAttributeList Attr = ParseCXX0XAttributes();
-    D.AddAttributes(Attr.AttrList, AttrEndLoc);
-  }
-
-  while (1) {
-    if (Tok.is(tok::l_paren)) {
-      // The paren may be part of a C++ direct initializer, eg. "int x(1);".
-      // In such a case, check if we actually have a function declarator; if it
-      // is not, the declarator has been fully parsed.
-      if (getLang().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) {
-        // When not in file scope, warn for ambiguous function declarators, just
-        // in case the author intended it as a variable definition.
-        bool warnIfAmbiguous = D.getContext() != Declarator::FileContext;
-        if (!isCXXFunctionDeclarator(warnIfAmbiguous))
-          break;
-      }
-      ParseFunctionDeclarator(ConsumeParen(), D);
-    } else if (Tok.is(tok::l_square)) {
-      ParseBracketDeclarator(D);
-    } else {
-      break;
-    }
-  }
+  ParsePostIdentifierDeclarator(D);
 }
 
 /// ParseParenDeclarator - We parsed the declarator D up to a paren.  This is
@@ -2710,15 +2714,26 @@
   if (isGrouping) {
     bool hadGroupingParens = D.hasGroupingParens();
     D.setGroupingParens(true);
-    if (AttrList)
-      D.AddAttributes(AttrList.take(), SourceLocation());
 
+    unsigned oldNumTypeObjects = D.getNumTypeObjects();
     ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
     // Match the ')'.
     SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, StartLoc);
 
     D.setGroupingParens(hadGroupingParens);
     D.SetRangeEnd(Loc);
+    // If we didn't parse a function, or if we didn't parse anything at all,
+    // attempt to parse parentheses, etc.
+    // This is so we don't break the invariant that function declarators
+    // have a Function DeclaratorChunk at index 0, etc.
+    unsigned newNumTypeObjects = D.getNumTypeObjects();
+    if (oldNumTypeObjects == newNumTypeObjects ||
+        D.getTypeObject(newNumTypeObjects-1).Kind !=
+        DeclaratorChunk::Function)
+      ParsePostIdentifierDeclarator(D);
+    D.AddTypeInfo(DeclaratorChunk::getGroupingParentheses(StartLoc,
+                                                          AttrList.take()),
+                  Loc);
     return;
   }
 
