[cfe-commits] r122871 - in /cfe/trunk: include/clang/AST/Type.h include/clang/AST/TypeLoc.h include/clang/Sema/AttributeList.h include/clang/Sema/DeclSpec.h include/clang/Sema/Sema.h lib/AST/TypeLoc.cpp lib/CodeGen/CGBlocks.cpp lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaStmt.cpp lib/Sema/SemaType.cpp lib/Sema/TreeTransform.h test/Sema/block-return.c test/Sema/stdcall-fastcall.c

John McCall rjmccall at apple.com
Wed Jan 5 04:14:39 PST 2011


Author: rjmccall
Date: Wed Jan  5 06:14:39 2011
New Revision: 122871

URL: http://llvm.org/viewvc/llvm-project?rev=122871&view=rev
Log:
Refactor the application of type attributes so that attributes from
the declaration-specifiers and on the declarator itself are moved
to the appropriate declarator chunk.  This permits a greatly
simplified model for how to apply these attributes, as well as
allowing a much more efficient query for the GC attribute.
Now all qualifier queries follow the same basic strategy of
"local qualifiers, local qualifiers on the canonical type,
then look through arrays".  This can be easily optimized by
changing the canonical qualified-array-type representation.

Do not process type attributes as decl attributes on declarations
with declarators.

When computing the type of a block, synthesize a prototype
function declarator chunk if the decl-spec type was not a
function.  This simplifies the logic for building block signatures.

Change the logic which inserts an objc_read_weak on a block
literal to only fire if the block has a __weak __block variable,
rather than if the return type of the block is __weak qualified,
which is not actually a sensible thing to ask.


Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/AST/TypeLoc.h
    cfe/trunk/include/clang/Sema/AttributeList.h
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/TypeLoc.cpp
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/Sema/block-return.c
    cfe/trunk/test/Sema/stdcall-fastcall.c

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Jan  5 06:14:39 2011
@@ -3728,11 +3728,6 @@
 
   if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
       return AT->getElementType().getObjCGCAttr();
-  if (const ObjCObjectPointerType *PT = CT->getAs<ObjCObjectPointerType>())
-    return PT->getPointeeType().getObjCGCAttr();
-  // We most look at all pointer types, not just pointer to interface types.
-  if (const PointerType *PT = CT->getAs<PointerType>())
-    return PT->getPointeeType().getObjCGCAttr();
   return Qualifiers::GCNone;
 }
 

Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Wed Jan  5 06:14:39 2011
@@ -133,7 +133,18 @@
   /// \brief Initializes this by copying its information from another
   /// TypeLoc of the same type.
   void initializeFullCopy(TypeLoc Other) const {
-    initializeFullCopyImpl(*this, Other);
+    assert(getType() == Other.getType());
+    size_t Size = getFullDataSize();
+    memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
+  }
+
+  /// \brief Initializes this by copying its information from another
+  /// TypeLoc of the same type.  The given size must be the full data
+  /// size.
+  void initializeFullCopy(TypeLoc Other, unsigned Size) const {
+    assert(getType() == Other.getType());
+    assert(getFullDataSize() == Size);
+    memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
   }
 
   friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {
@@ -148,7 +159,6 @@
 
 private:
   static void initializeImpl(TypeLoc TL, SourceLocation Loc);
-  static void initializeFullCopyImpl(TypeLoc TL, TypeLoc Other);
   static TypeLoc getNextTypeLocImpl(TypeLoc TL);
   static TypeLoc IgnoreParensImpl(TypeLoc TL);
   static SourceRange getLocalSourceRangeImpl(TypeLoc TL);

Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Wed Jan  5 06:14:39 2011
@@ -46,7 +46,10 @@
   unsigned NumArgs;
   AttributeList *Next;
   bool DeclspecAttribute, CXX0XAttribute;
-  mutable bool Invalid; /// True if already diagnosed as invalid.
+
+  /// True if already diagnosed as invalid.
+  mutable bool Invalid;
+
   AttributeList(const AttributeList &); // DO NOT IMPLEMENT
   void operator=(const AttributeList &); // DO NOT IMPLEMENT
   void operator delete(void *); // DO NOT IMPLEMENT
@@ -302,6 +305,10 @@
   void clear() { list = 0; }
   AttributeList *getList() const { return list; }
 
+  /// Returns a reference to the attribute list.  Try not to introduce
+  /// dependencies on this method, it may not be long-lived.
+  AttributeList *&getListRef() { return list; }
+
 private:
   AttributeList *list;
 };

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Wed Jan  5 06:14:39 2011
@@ -1002,6 +1002,7 @@
   };
 
   union {
+    TypeInfoCommon        Common;
     PointerTypeInfo       Ptr;
     ReferenceTypeInfo     Ref;
     ArrayTypeInfo         Arr;
@@ -1026,19 +1027,12 @@
   /// getAttrs - If there are attributes applied to this declaratorchunk, return
   /// them.
   const AttributeList *getAttrs() const {
-    switch (Kind) {
-    case Pointer:       return Ptr.AttrList;
-    case Reference:     return Ref.AttrList;
-    case MemberPointer: return Mem.AttrList;
-    case Array:         return Arr.AttrList;
-    case Function:      return Fun.AttrList;
-    case BlockPointer:  return Cls.AttrList;
-    case Paren:         return 0;
-    }
-    llvm_unreachable("Unknown declarator kind!");
-    return 0;
+    return Common.AttrList;
   }
 
+  AttributeList *&getAttrListRef() {
+    return Common.AttrList;
+  }
 
   /// getPointer - Return a DeclaratorChunk for a pointer.
   ///
@@ -1133,6 +1127,7 @@
     I.Kind          = Paren;
     I.Loc           = LParenLoc;
     I.EndLoc        = RParenLoc;
+    I.Common.AttrList = 0;
     return I;
   }
 
@@ -1337,6 +1332,11 @@
       SetRangeEnd(EndLoc);
   }
 
+  /// AddInnermostTypeInfo - Add a new innermost chunk to this declarator.
+  void AddInnermostTypeInfo(const DeclaratorChunk &TI) {
+    DeclTypeInfo.insert(DeclTypeInfo.begin(), TI);
+  }
+
   /// getNumTypeObjects() - Return the number of types applied to this
   /// declarator.
   unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); }
@@ -1428,6 +1428,8 @@
   const AttributeList *getAttributes() const { return AttrList; }
   AttributeList *getAttributes() { return AttrList; }
 
+  AttributeList *&getAttrListRef() { return AttrList; }
+
   /// hasAttributes - do we contain any attributes?
   bool hasAttributes() const {
     if (getAttributes() || getDeclSpec().hasAttributes()) return true;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Jan  5 06:14:39 2011
@@ -1370,6 +1370,10 @@
   void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
   void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL);
 
+  bool CheckRegparmAttr(const AttributeList &attr, unsigned &value);
+  bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC);
+  bool CheckNoReturnAttr(const AttributeList &attr);
+
   void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
                            bool &IncompleteImpl, unsigned DiagID);
   void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod,

Modified: cfe/trunk/lib/AST/TypeLoc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypeLoc.cpp (original)
+++ cfe/trunk/lib/AST/TypeLoc.cpp Wed Jan  5 06:14:39 2011
@@ -94,13 +94,6 @@
   }
 }
 
-/// \brief Initializes a type location by copying all its data from
-/// another type location of the same type.
-void TypeLoc::initializeFullCopyImpl(TypeLoc TL, TypeLoc Other) {
-  assert(TL.getType() == Other.getType() && "Must copy from same type");
-  memcpy(TL.getOpaqueData(), Other.getOpaqueData(), TL.getFullDataSize());
-}
-
 SourceLocation TypeLoc::getBeginLoc() const {
   TypeLoc Cur = *this;
   while (true) {

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Wed Jan  5 06:14:39 2011
@@ -198,6 +198,8 @@
   llvm::Constant *C;
   llvm::Value *V;
 
+  bool hasWeakBlockVariable = false;
+
   {
     llvm::Constant *BlockVarLayout;
     // C = BuildBlockStructInitlist();
@@ -268,6 +270,8 @@
       const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
       QualType Ty = E->getType();
       if (BDRE && BDRE->isByRef()) {
+        if (BDRE->getDecl()->getType().isObjCGCWeak())
+          hasWeakBlockVariable = true;
         Types[i+BlockFields] = 
           llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
       } else if (BDRE && BDRE->getDecl()->getType()->isReferenceType()) {
@@ -404,18 +408,22 @@
 
   QualType BPT = BE->getType();
   V = Builder.CreateBitCast(V, ConvertType(BPT));
-  // See if this is a __weak block variable and the must call objc_read_weak
-  // on it.
-  const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>();
-  QualType RES = ftype->getResultType();
-  if (RES.isObjCGCWeak()) {
+
+  // We must call objc_read_weak on the block literal itself if it closes
+  // on any __weak __block variables.  For some reason.
+  if (hasWeakBlockVariable) {
+    const llvm::Type *OrigTy = V->getType();
+
     // Must cast argument to id*
     const llvm::Type *ObjectPtrTy = 
       ConvertType(CGM.getContext().getObjCIdType());
     const llvm::Type *PtrObjectPtrTy = 
       llvm::PointerType::getUnqual(ObjectPtrTy);
     V = Builder.CreateBitCast(V, PtrObjectPtrTy);
-    V =  CGM.getObjCRuntime().EmitObjCWeakRead(*this, V);
+    V = CGM.getObjCRuntime().EmitObjCWeakRead(*this, V);
+
+    // Cast back to the original type.
+    V = Builder.CreateBitCast(V, OrigTy);
   }
   return V;
 }

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Jan  5 06:14:39 2011
@@ -78,6 +78,13 @@
   return isa<BlockDecl>(d);
 }
 
+/// Return true if the given decl has a declarator that should have
+/// been processed by Sema::GetTypeForDeclarator.
+static bool hasDeclarator(const Decl *d) {
+  // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
+  return isa<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefDecl>(d);
+}
+
 /// hasFunctionProto - Return true if the given decl has a argument
 /// information. This decl should have already passed
 /// isFunctionOrMethod or isFunctionOrMethodOrBlock.
@@ -766,10 +773,28 @@
       << Attr.getName() << 12 /* variable */;
 }
 
-static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
-  /* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */
-  assert(Attr.isInvalid() == false);
-  d->addAttr(::new (S.Context) NoReturnAttr(Attr.getLoc(), S.Context));
+static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) {
+  if (hasDeclarator(d)) return;
+
+  if (S.CheckNoReturnAttr(attr)) return;
+
+  if (!isa<ObjCMethodDecl>(d)) {
+    S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  d->addAttr(::new (S.Context) NoReturnAttr(attr.getLoc(), S.Context));
+}
+
+bool Sema::CheckNoReturnAttr(const AttributeList &attr) {
+  if (attr.getNumArgs() != 0) {
+    Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    attr.setInvalid();
+    return true;
+  }
+
+  return false;
 }
 
 static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
@@ -2251,26 +2276,36 @@
   d->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context));
 }
 
-static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
-  // Diagnostic is emitted elsewhere: here we store the (valid) Attr
+static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) {
+  if (hasDeclarator(d)) return;
+
+  // Diagnostic is emitted elsewhere: here we store the (valid) attr
   // in the Decl node for syntactic reasoning, e.g., pretty-printing.
-  assert(Attr.isInvalid() == false);
+  CallingConv CC;
+  if (S.CheckCallingConvAttr(attr, CC))
+    return;
 
-  switch (Attr.getKind()) {
+  if (!isa<ObjCMethodDecl>(d)) {
+    S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << attr.getName() << 0 /*function*/;
+    return;
+  }
+
+  switch (attr.getKind()) {
   case AttributeList::AT_fastcall:
-    d->addAttr(::new (S.Context) FastCallAttr(Attr.getLoc(), S.Context));
+    d->addAttr(::new (S.Context) FastCallAttr(attr.getLoc(), S.Context));
     return;
   case AttributeList::AT_stdcall:
-    d->addAttr(::new (S.Context) StdCallAttr(Attr.getLoc(), S.Context));
+    d->addAttr(::new (S.Context) StdCallAttr(attr.getLoc(), S.Context));
     return;
   case AttributeList::AT_thiscall:
-    d->addAttr(::new (S.Context) ThisCallAttr(Attr.getLoc(), S.Context));
+    d->addAttr(::new (S.Context) ThisCallAttr(attr.getLoc(), S.Context));
     return;
   case AttributeList::AT_cdecl:
-    d->addAttr(::new (S.Context) CDeclAttr(Attr.getLoc(), S.Context));
+    d->addAttr(::new (S.Context) CDeclAttr(attr.getLoc(), S.Context));
     return;
   case AttributeList::AT_pascal:
-    d->addAttr(::new (S.Context) PascalAttr(Attr.getLoc(), S.Context));
+    d->addAttr(::new (S.Context) PascalAttr(attr.getLoc(), S.Context));
     return;
   default:
     llvm_unreachable("unexpected attribute kind");
@@ -2278,42 +2313,83 @@
   }
 }
 
-static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
-  // check the attribute arguments.
-  if (Attr.getNumArgs() != 1) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
-    return;
+bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {
+  if (attr.isInvalid())
+    return true;
+
+  if (attr.getNumArgs() != 0) {
+    Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    attr.setInvalid();
+    return true;
   }
 
-  if (!isFunctionOrMethod(d)) {
-    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
-    << Attr.getName() << 0 /*function*/;
+  // TODO: diagnose uses of these conventions on the wrong target.
+  switch (attr.getKind()) {
+  case AttributeList::AT_cdecl: CC = CC_C; break;
+  case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
+  case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
+  case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break;
+  case AttributeList::AT_pascal: CC = CC_X86Pascal; break;
+  default: llvm_unreachable("unexpected attribute kind"); return true;
+  }
+
+  return false;
+}
+
+static void HandleRegparmAttr(Decl *d, const AttributeList &attr, Sema &S) {
+  if (hasDeclarator(d)) return;
+
+  unsigned numParams;
+  if (S.CheckRegparmAttr(attr, numParams))
+    return;
+
+  if (!isa<ObjCMethodDecl>(d)) {
+    S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << attr.getName() << 0 /*function*/;
     return;
   }
 
-  Expr *NumParamsExpr = Attr.getArg(0);
+  d->addAttr(::new (S.Context) RegparmAttr(attr.getLoc(), S.Context, numParams));
+}
+
+/// Checks a regparm attribute, returning true if it is ill-formed and
+/// otherwise setting numParams to the appropriate value.
+bool Sema::CheckRegparmAttr(const AttributeList &attr, unsigned &numParams) {
+  if (attr.isInvalid())
+    return true;
+
+  if (attr.getNumArgs() != 1) {
+    Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    attr.setInvalid();
+    return true;
+  }
+
+  Expr *NumParamsExpr = attr.getArg(0);
   llvm::APSInt NumParams(32);
   if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() ||
-      !NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+      !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) {
+    Diag(attr.getLoc(), diag::err_attribute_argument_not_int)
       << "regparm" << NumParamsExpr->getSourceRange();
-    return;
+    attr.setInvalid();
+    return true;
   }
 
-  if (S.Context.Target.getRegParmMax() == 0) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
+  if (Context.Target.getRegParmMax() == 0) {
+    Diag(attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
       << NumParamsExpr->getSourceRange();
-    return;
+    attr.setInvalid();
+    return true;
   }
 
-  if (NumParams.getLimitedValue(255) > S.Context.Target.getRegParmMax()) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
-      << S.Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange();
-    return;
+  numParams = NumParams.getZExtValue();
+  if (numParams > Context.Target.getRegParmMax()) {
+    Diag(attr.getLoc(), diag::err_attribute_regparm_invalid_number)
+      << Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange();
+    attr.setInvalid();
+    return true;
   }
 
-  d->addAttr(::new (S.Context) RegparmAttr(Attr.getLoc(), S.Context,
-                                           NumParams.getZExtValue()));
+  return false;
 }
 
 static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jan  5 06:14:39 2011
@@ -8297,31 +8297,50 @@
 
 void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
   assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!");
+  assert(ParamInfo.getContext() == Declarator::BlockLiteralContext);
   BlockScopeInfo *CurBlock = getCurBlock();
 
   TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope);
-  CurBlock->TheDecl->setSignatureAsWritten(Sig);
   QualType T = Sig->getType();
 
-  bool isVariadic;
-  QualType RetTy;
-  if (const FunctionType *Fn = T->getAs<FunctionType>()) {
-    CurBlock->FunctionType = T;
-    RetTy = Fn->getResultType();
-    isVariadic =
-      !isa<FunctionProtoType>(Fn) || cast<FunctionProtoType>(Fn)->isVariadic();
-  } else {
-    RetTy = T;
-    isVariadic = false;
+  // GetTypeForDeclarator always produces a function type for a block
+  // literal signature.  Furthermore, it is always a FunctionProtoType
+  // unless the function was written with a typedef.
+  assert(T->isFunctionType() &&
+         "GetTypeForDeclarator made a non-function block signature");
+
+  // Look for an explicit signature in that function type.
+  FunctionProtoTypeLoc ExplicitSignature;
+
+  TypeLoc tmp = Sig->getTypeLoc().IgnoreParens();
+  if (isa<FunctionProtoTypeLoc>(tmp)) {
+    ExplicitSignature = cast<FunctionProtoTypeLoc>(tmp);
+
+    // Check whether that explicit signature was synthesized by
+    // GetTypeForDeclarator.  If so, don't save that as part of the
+    // written signature.
+    if (ExplicitSignature.getLParenLoc() ==
+        ExplicitSignature.getRParenLoc()) {
+      // This would be much cheaper if we stored TypeLocs instead of
+      // TypeSourceInfos.
+      TypeLoc Result = ExplicitSignature.getResultLoc();
+      unsigned Size = Result.getFullDataSize();
+      Sig = Context.CreateTypeSourceInfo(Result.getType(), Size);
+      Sig->getTypeLoc().initializeFullCopy(Result, Size);
+
+      ExplicitSignature = FunctionProtoTypeLoc();
+    }
   }
 
-  CurBlock->TheDecl->setIsVariadic(isVariadic);
+  CurBlock->TheDecl->setSignatureAsWritten(Sig);
+  CurBlock->FunctionType = T;
 
-  // Don't allow returning an array by value.
-  if (RetTy->isArrayType()) {
-    Diag(ParamInfo.getSourceRange().getBegin(), diag::err_block_returns_array);
-    return;
-  }
+  const FunctionType *Fn = T->getAs<FunctionType>();
+  QualType RetTy = Fn->getResultType();
+  bool isVariadic =
+    (isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic());
+
+  CurBlock->TheDecl->setIsVariadic(isVariadic);
 
   // Don't allow returning a objc interface by value.
   if (RetTy->isObjCObjectType()) {
@@ -8339,11 +8358,9 @@
 
   // Push block parameters from the declarator if we had them.
   llvm::SmallVector<ParmVarDecl*, 8> Params;
-  if (isa<FunctionProtoType>(T.IgnoreParens())) {
-    FunctionProtoTypeLoc TL
-      = cast<FunctionProtoTypeLoc>(Sig->getTypeLoc().IgnoreParens());
-    for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
-      ParmVarDecl *Param = TL.getArg(I);
+  if (ExplicitSignature) {
+    for (unsigned I = 0, E = ExplicitSignature.getNumArgs(); I != E; ++I) {
+      ParmVarDecl *Param = ExplicitSignature.getArg(I);
       if (Param->getIdentifier() == 0 &&
           !Param->isImplicit() &&
           !Param->isInvalidDecl() &&

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Jan  5 06:14:39 2011
@@ -1153,7 +1153,7 @@
   }
   QualType FnRetType = CurBlock->ReturnType;
 
-  if (CurBlock->TheDecl->hasAttr<NoReturnAttr>()) {
+  if (CurBlock->FunctionType->getAs<FunctionType>()->getNoReturnAttr()) {
     Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr)
       << getCurFunctionOrMethodDecl()->getDeclName();
     return StmtError();

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Jan  5 06:14:39 2011
@@ -70,37 +70,464 @@
   return false;
 }
 
-typedef std::pair<const AttributeList*,QualType> DelayedAttribute;
-typedef llvm::SmallVectorImpl<DelayedAttribute> DelayedAttributeSet;
+// objc_gc applies to Objective-C pointers or, otherwise, to the
+// smallest available pointer type (i.e. 'void*' in 'void**').
+#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
+    case AttributeList::AT_objc_gc
+
+// Function type attributes.
+#define FUNCTION_TYPE_ATTRS_CASELIST \
+    case AttributeList::AT_noreturn: \
+    case AttributeList::AT_cdecl: \
+    case AttributeList::AT_fastcall: \
+    case AttributeList::AT_stdcall: \
+    case AttributeList::AT_thiscall: \
+    case AttributeList::AT_pascal: \
+    case AttributeList::AT_regparm
 
-static void ProcessTypeAttributeList(Sema &S, QualType &Type,
-                                     bool IsDeclSpec,
-                                     const AttributeList *Attrs,
-                                     DelayedAttributeSet &DelayedFnAttrs);
-static bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr);
-
-static void ProcessDelayedFnAttrs(Sema &S, QualType &Type,
-                                  DelayedAttributeSet &Attrs) {
-  for (DelayedAttributeSet::iterator I = Attrs.begin(),
-         E = Attrs.end(); I != E; ++I)
-    if (ProcessFnAttr(S, Type, *I->first)) {
-      S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
-        << I->first->getName() << I->second;
-      // Avoid any further processing of this attribute.
-      I->first->setInvalid();
-    }
-  Attrs.clear();
-}
-
-static void DiagnoseDelayedFnAttrs(Sema &S, DelayedAttributeSet &Attrs) {
-  for (DelayedAttributeSet::iterator I = Attrs.begin(),
-         E = Attrs.end(); I != E; ++I) {
-    S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
-      << I->first->getName() << I->second;
-    // Avoid any further processing of this attribute.
-    I->first->setInvalid();
+namespace {
+  /// An object which stores processing state for the entire
+  /// GetTypeForDeclarator process.
+  class TypeProcessingState {
+    Sema &sema;
+
+    /// The declarator being processed.
+    Declarator &declarator;
+
+    /// The index of the declarator chunk we're currently processing.
+    /// May be the total number of valid chunks, indicating the
+    /// DeclSpec.
+    unsigned chunkIndex;
+
+    /// Whether there are non-trivial modifications to the decl spec.
+    bool trivial;
+
+    /// The original set of attributes on the DeclSpec.
+    llvm::SmallVector<AttributeList*, 2> savedAttrs;
+
+    /// A list of attributes to diagnose the uselessness of when the
+    /// processing is complete.
+    llvm::SmallVector<AttributeList*, 2> ignoredTypeAttrs;
+
+  public:
+    TypeProcessingState(Sema &sema, Declarator &declarator)
+      : sema(sema), declarator(declarator),
+        chunkIndex(declarator.getNumTypeObjects()),
+        trivial(true) {}
+
+    Sema &getSema() const {
+      return sema;
+    }
+
+    Declarator &getDeclarator() const {
+      return declarator;
+    }
+
+    unsigned getCurrentChunkIndex() const {
+      return chunkIndex;
+    }
+
+    void setCurrentChunkIndex(unsigned idx) {
+      assert(idx <= declarator.getNumTypeObjects());
+      chunkIndex = idx;
+    }
+
+    AttributeList *&getCurrentAttrListRef() const {
+      assert(chunkIndex <= declarator.getNumTypeObjects());
+      if (chunkIndex == declarator.getNumTypeObjects())
+        return getMutableDeclSpec().getAttributes().getListRef();
+      return declarator.getTypeObject(chunkIndex).getAttrListRef();
+    }
+
+    /// Save the current set of attributes on the DeclSpec.
+    void saveDeclSpecAttrs() {
+      // Don't try to save them multiple times.
+      if (!savedAttrs.empty()) return;
+
+      DeclSpec &spec = getMutableDeclSpec();
+      for (AttributeList *attr = spec.getAttributes().getList(); attr;
+             attr = attr->getNext())
+        savedAttrs.push_back(attr);
+      trivial &= savedAttrs.empty();
+    }
+
+    /// Record that we had nowhere to put the given type attribute.
+    /// We will diagnose such attributes later.
+    void addIgnoredTypeAttr(AttributeList &attr) {
+      ignoredTypeAttrs.push_back(&attr);
+    }
+
+    /// Diagnose all the ignored type attributes, given that the
+    /// declarator worked out to the given type.
+    void diagnoseIgnoredTypeAttrs(QualType type) const {
+      for (llvm::SmallVectorImpl<AttributeList*>::const_iterator
+             i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end();
+           i != e; ++i) {
+        AttributeList &attr = **i;
+        getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type)
+          << attr.getName() << type;
+      }
+    }
+
+    ~TypeProcessingState() {
+      if (trivial) return;
+
+      restoreDeclSpecAttrs();
+    }
+
+  private:
+    DeclSpec &getMutableDeclSpec() const {
+      return const_cast<DeclSpec&>(declarator.getDeclSpec());
+    }
+
+    void restoreDeclSpecAttrs() {
+      assert(!savedAttrs.empty());
+      getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
+      for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
+        savedAttrs[i]->setNext(savedAttrs[i+1]);
+      savedAttrs.back()->setNext(0);
+    }
+  };
+
+  /// Basically std::pair except that we really want to avoid an
+  /// implicit operator= for safety concerns.  It's also a minor
+  /// link-time optimization for this to be a private type.
+  struct AttrAndList {
+    /// The attribute.
+    AttributeList &first;
+
+    /// The head of the list the attribute is currently in.
+    AttributeList *&second;
+
+    AttrAndList(AttributeList &attr, AttributeList *&head)
+      : first(attr), second(head) {}
+  };
+}
+
+namespace llvm {
+  template <> struct isPodLike<AttrAndList> {
+    static const bool value = true;
+  };
+}
+
+static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
+  attr.setNext(head);
+  head = &attr;
+}
+
+static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) {
+  if (head == &attr) {
+    head = attr.getNext();
+    return;
+  }
+
+  AttributeList *cur = head;
+  while (true) {
+    assert(cur && cur->getNext() && "ran out of attrs?");
+    if (cur->getNext() == &attr) {
+      cur->setNext(attr.getNext());
+      return;
+    }
+    cur = cur->getNext();
   }
-  Attrs.clear();
+}
+
+static void moveAttrFromListToList(AttributeList &attr,
+                                   AttributeList *&fromList,
+                                   AttributeList *&toList) {
+  spliceAttrOutOfList(attr, fromList);
+  spliceAttrIntoList(attr, toList);
+}
+
+static void processTypeAttrs(TypeProcessingState &state,
+                             QualType &type, bool isDeclSpec,
+                             AttributeList *attrs);
+
+static bool handleFunctionTypeAttr(TypeProcessingState &state,
+                                   AttributeList &attr,
+                                   QualType &type);
+
+static bool handleObjCGCTypeAttr(TypeProcessingState &state,
+                                 AttributeList &attr, QualType &type);
+
+static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
+                                      AttributeList &attr, QualType &type) {
+  // Right now, we have exactly one of these attributes: objc_gc.
+  assert(attr.getKind() == AttributeList::AT_objc_gc);
+  return handleObjCGCTypeAttr(state, attr, type);
+}
+
+/// Given that an objc_gc attribute was written somewhere on a
+/// declaration *other* than on the declarator itself (for which, use
+/// distributeObjCPointerTypeAttrFromDeclarator), and given that it
+/// didn't apply in whatever position it was written in, try to move
+/// it to a more appropriate position.
+static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
+                                          AttributeList &attr,
+                                          QualType type) {
+  Declarator &declarator = state.getDeclarator();
+  for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
+    DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
+    switch (chunk.Kind) {
+    case DeclaratorChunk::Pointer:
+    case DeclaratorChunk::BlockPointer:
+      moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
+                             chunk.getAttrListRef());
+      return;
+
+    case DeclaratorChunk::Paren:
+    case DeclaratorChunk::Array:
+      continue;
+
+    // Don't walk through these.
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::Function:
+    case DeclaratorChunk::MemberPointer:
+      goto error;
+    }
+  }
+ error:
+  
+  state.getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type)
+    << attr.getName() << type;
+}
+
+/// Distribute an objc_gc type attribute that was written on the
+/// declarator.
+static void
+distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
+                                            AttributeList &attr,
+                                            QualType &declSpecType) {
+  Declarator &declarator = state.getDeclarator();
+
+  // objc_gc goes on the innermost pointer to something that's not a
+  // pointer.
+  unsigned innermost = -1U;
+  bool considerDeclSpec = true;
+  for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
+    DeclaratorChunk &chunk = declarator.getTypeObject(i);
+    switch (chunk.Kind) {
+    case DeclaratorChunk::Pointer:
+    case DeclaratorChunk::BlockPointer:
+      innermost = i;
+      return;
+
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::MemberPointer:
+    case DeclaratorChunk::Paren:
+    case DeclaratorChunk::Array:
+      continue;
+
+    case DeclaratorChunk::Function:
+      considerDeclSpec = false;
+      goto done;
+    }
+  }
+ done:
+
+  // That might actually be the decl spec if we weren't blocked by
+  // anything in the declarator.
+  if (considerDeclSpec) {
+    if (handleObjCPointerTypeAttr(state, attr, declSpecType))
+      return;
+  }
+
+  // Otherwise, if we found an appropriate chunk, splice the attribute
+  // into it.
+  if (innermost != -1U) {
+    moveAttrFromListToList(attr, declarator.getAttrListRef(),
+                       declarator.getTypeObject(innermost).getAttrListRef());
+    return;
+  }
+
+  // Otherwise, diagnose when we're done building the type.
+  spliceAttrOutOfList(attr, declarator.getAttrListRef());
+  state.addIgnoredTypeAttr(attr);
+}
+
+/// A function type attribute was written somewhere in a declaration
+/// *other* than on the declarator itself or in the decl spec.  Given
+/// that it didn't apply in whatever position it was written in, try
+/// to move it to a more appropriate position.
+static void distributeFunctionTypeAttr(TypeProcessingState &state,
+                                       AttributeList &attr,
+                                       QualType type) {
+  Declarator &declarator = state.getDeclarator();
+
+  // Try to push the attribute from the return type of a function to
+  // the function itself.
+  for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
+    DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
+    switch (chunk.Kind) {
+    case DeclaratorChunk::Function:
+      moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
+                             chunk.getAttrListRef());
+      return;
+
+    case DeclaratorChunk::Paren:
+    case DeclaratorChunk::Pointer:
+    case DeclaratorChunk::BlockPointer:
+    case DeclaratorChunk::Array:
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::MemberPointer:
+      continue;
+    }
+  }
+  
+  state.getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type)
+    << attr.getName() << type;
+}
+
+/// Try to distribute a function type attribute to the innermost
+/// function chunk or type.  Returns true if the attribute was
+/// distributed, false if no location was found.
+static bool
+distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
+                                      AttributeList &attr,
+                                      AttributeList *&attrList,
+                                      QualType &declSpecType) {
+  Declarator &declarator = state.getDeclarator();
+
+  // Put it on the innermost function chunk, if there is one.
+  for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
+    DeclaratorChunk &chunk = declarator.getTypeObject(i);
+    if (chunk.Kind != DeclaratorChunk::Function) continue;
+
+    moveAttrFromListToList(attr, attrList, chunk.getAttrListRef());
+    return true;
+  }
+
+  return handleFunctionTypeAttr(state, attr, declSpecType);
+}
+
+/// A function type attribute was written in the decl spec.  Try to
+/// apply it somewhere.
+static void
+distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
+                                       AttributeList &attr,
+                                       QualType &declSpecType) {
+  state.saveDeclSpecAttrs();
+
+  // Try to distribute to the innermost.
+  if (distributeFunctionTypeAttrToInnermost(state, attr,
+                                            state.getCurrentAttrListRef(),
+                                            declSpecType))
+    return;
+
+  // If that failed, diagnose the bad attribute when the declarator is
+  // fully built.
+  state.addIgnoredTypeAttr(attr);
+}
+
+/// A function type attribute was written on the declarator.  Try to
+/// apply it somewhere.
+static void
+distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
+                                         AttributeList &attr,
+                                         QualType &declSpecType) {
+  Declarator &declarator = state.getDeclarator();
+
+  // Try to distribute to the innermost.
+  if (distributeFunctionTypeAttrToInnermost(state, attr,
+                                            declarator.getAttrListRef(),
+                                            declSpecType))
+    return;
+
+  // If that failed, diagnose the bad attribute when the declarator is
+  // fully built.
+  spliceAttrOutOfList(attr, declarator.getAttrListRef());
+  state.addIgnoredTypeAttr(attr);
+}
+
+/// \brief Given that there are attributes written on the declarator
+/// itself, try to distribute any type attributes to the appropriate
+/// declarator chunk.
+///
+/// These are attributes like the following:
+///   int f ATTR;
+///   int (f ATTR)();
+/// but not necessarily this:
+///   int f() ATTR;
+static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
+                                              QualType &declSpecType) {
+  // Collect all the type attributes from the declarator itself.
+  assert(state.getDeclarator().getAttributes() && "declarator has no attrs!");
+  AttributeList *attr = state.getDeclarator().getAttributes();
+  AttributeList *next;
+  do {
+    next = attr->getNext();
+
+    switch (attr->getKind()) {
+    OBJC_POINTER_TYPE_ATTRS_CASELIST:
+      distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
+      break;
+
+    FUNCTION_TYPE_ATTRS_CASELIST:
+      distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
+      break;
+
+    default:
+      break;
+    }
+  } while ((attr = next));
+}
+
+/// Add a synthetic '()' to a block-literal declarator if it is
+/// required, given the return type.
+static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
+                                          QualType declSpecType) {
+  Declarator &declarator = state.getDeclarator();
+
+  // First, check whether the declarator would produce a function,
+  // i.e. whether the innermost semantic chunk is a function.
+  if (declarator.isFunctionDeclarator()) {
+    // If so, make that declarator a prototyped declarator.
+    declarator.getFunctionTypeInfo().hasPrototype = true;
+    return;
+  }
+
+  // If there are any type objects, the type as written won't
+  // name a function, regardless of the decl spec type.  This
+  // is because a block signature declarator is always an
+  // abstract-declarator, and abstract-declarators can't just
+  // be parentheses chunks.  Therefore we need to build a function
+  // chunk unless there are no type objects and the decl spec
+  // type is a function.
+  if (!declarator.getNumTypeObjects() && declSpecType->isFunctionType())
+    return;
+
+#ifndef NDEBUG
+  if (declarator.getNumTypeObjects()) {
+    bool isOnlyParens = true;
+    for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
+      if (declarator.getTypeObject(i).Kind != DeclaratorChunk::Paren) {
+        isOnlyParens = false;
+        break;
+      }
+    }
+    assert(!isOnlyParens &&
+           "non-empty abstract-declarator contained only parens!");
+#endif
+  }
+
+  // Otherwise, we need to fake up a function declarator.
+  SourceLocation loc = declarator.getSourceRange().getBegin();
+
+  // ...and *prepend* it to the declarator.
+  declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
+                             ParsedAttributes(),
+                             /*proto*/ true,
+                             /*variadic*/ false, SourceLocation(),
+                             /*args*/ 0, 0,
+                             /*type quals*/ 0,
+                             /*EH*/ false, SourceLocation(), false, 0, 0, 0,
+                             /*parens*/ loc, loc,
+                             declarator));
+
+  // For consistency, make sure the state still has us as processing
+  // the decl spec.
+  assert(state.getCurrentChunkIndex() == declarator.getNumTypeObjects() - 1);
+  state.setCurrentChunkIndex(declarator.getNumTypeObjects());
 }
 
 /// \brief Convert the specified declspec to the appropriate type
@@ -108,17 +535,17 @@
 /// \param D  the declarator containing the declaration specifier.
 /// \returns The type described by the declaration specifiers.  This function
 /// never returns null.
-static QualType ConvertDeclSpecToType(Sema &TheSema,
-                                      Declarator &TheDeclarator,
-                                      DelayedAttributeSet &Delayed) {
+static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) {
   // FIXME: Should move the logic from DeclSpec::Finish to here for validity
   // checking.
-  const DeclSpec &DS = TheDeclarator.getDeclSpec();
-  SourceLocation DeclLoc = TheDeclarator.getIdentifierLoc();
+
+  Declarator &declarator = state.getDeclarator();
+  const DeclSpec &DS = declarator.getDeclSpec();
+  SourceLocation DeclLoc = declarator.getIdentifierLoc();
   if (DeclLoc.isInvalid())
     DeclLoc = DS.getSourceRange().getBegin();
   
-  ASTContext &Context = TheSema.Context;
+  ASTContext &Context = S.Context;
 
   QualType Result;
   switch (DS.getTypeSpecType()) {
@@ -140,13 +567,13 @@
     if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
       Result = Context.WCharTy;
     else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
-      TheSema.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
+      S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
         << DS.getSpecifierName(DS.getTypeSpecType());
       Result = Context.getSignedWCharType();
     } else {
       assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
         "Unknown TSS value");
-      TheSema.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
+      S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
         << DS.getSpecifierName(DS.getTypeSpecType());
       Result = Context.getUnsignedWCharType();
     }
@@ -173,7 +600,7 @@
     
     // If this is a missing declspec in a block literal return context, then it
     // is inferred from the return statements inside the block.
-    if (isOmittedBlockReturnType(TheDeclarator)) {
+    if (isOmittedBlockReturnType(declarator)) {
       Result = Context.DependentTy;
       break;
     }
@@ -185,11 +612,11 @@
     // allowed to be completely missing a declspec.  This is handled in the
     // parser already though by it pretending to have seen an 'int' in this
     // case.
-    if (TheSema.getLangOptions().ImplicitInt) {
+    if (S.getLangOptions().ImplicitInt) {
       // In C89 mode, we only warn if there is a completely missing declspec
       // when one is not allowed.
       if (DS.isEmpty()) {
-        TheSema.Diag(DeclLoc, diag::ext_missing_declspec)
+        S.Diag(DeclLoc, diag::ext_missing_declspec)
           << DS.getSourceRange()
         << FixItHint::CreateInsertion(DS.getSourceRange().getBegin(), "int");
       }
@@ -199,17 +626,17 @@
       // specifiers in each declaration, and in the specifier-qualifier list in
       // each struct declaration and type name."
       // FIXME: Does Microsoft really have the implicit int extension in C++?
-      if (TheSema.getLangOptions().CPlusPlus &&
-          !TheSema.getLangOptions().Microsoft) {
-        TheSema.Diag(DeclLoc, diag::err_missing_type_specifier)
+      if (S.getLangOptions().CPlusPlus &&
+          !S.getLangOptions().Microsoft) {
+        S.Diag(DeclLoc, diag::err_missing_type_specifier)
           << DS.getSourceRange();
 
         // When this occurs in C++ code, often something is very broken with the
         // value being declared, poison it as invalid so we don't get chains of
         // errors.
-        TheDeclarator.setInvalidType(true);
+        declarator.setInvalidType(true);
       } else {
-        TheSema.Diag(DeclLoc, diag::ext_missing_type_specifier)
+        S.Diag(DeclLoc, diag::ext_missing_type_specifier)
           << DS.getSourceRange();
       }
     }
@@ -225,9 +652,9 @@
         Result = Context.LongLongTy;
           
         // long long is a C99 feature.
-        if (!TheSema.getLangOptions().C99 &&
-            !TheSema.getLangOptions().CPlusPlus0x)
-          TheSema.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong);
+        if (!S.getLangOptions().C99 &&
+            !S.getLangOptions().CPlusPlus0x)
+          S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong);
         break;
       }
     } else {
@@ -239,9 +666,9 @@
         Result = Context.UnsignedLongLongTy;
           
         // long long is a C99 feature.
-        if (!TheSema.getLangOptions().C99 &&
-            !TheSema.getLangOptions().CPlusPlus0x)
-          TheSema.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong);
+        if (!S.getLangOptions().C99 &&
+            !S.getLangOptions().CPlusPlus0x)
+          S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong);
         break;
       }
     }
@@ -258,9 +685,9 @@
   case DeclSpec::TST_decimal32:    // _Decimal32
   case DeclSpec::TST_decimal64:    // _Decimal64
   case DeclSpec::TST_decimal128:   // _Decimal128
-    TheSema.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
+    S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
     Result = Context.IntTy;
-    TheDeclarator.setInvalidType(true);
+    declarator.setInvalidType(true);
     break;
   case DeclSpec::TST_class:
   case DeclSpec::TST_enum:
@@ -270,12 +697,12 @@
     if (!D) {
       // This can happen in C++ with ambiguous lookups.
       Result = Context.IntTy;
-      TheDeclarator.setInvalidType(true);
+      declarator.setInvalidType(true);
       break;
     }
 
     // If the type is deprecated or unavailable, diagnose it.
-    TheSema.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc());
+    S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc());
     
     assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
            DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
@@ -284,23 +711,22 @@
     Result = Context.getTypeDeclType(D);
 
     // In C++, make an ElaboratedType.
-    if (TheSema.getLangOptions().CPlusPlus) {
+    if (S.getLangOptions().CPlusPlus) {
       ElaboratedTypeKeyword Keyword
         = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
-      Result = TheSema.getElaboratedType(Keyword, DS.getTypeSpecScope(),
-                                         Result);
+      Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result);
     }
     if (D->isInvalidDecl())
-      TheDeclarator.setInvalidType(true);
+      declarator.setInvalidType(true);
     break;
   }
   case DeclSpec::TST_typename: {
     assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
            DS.getTypeSpecSign() == 0 &&
            "Can't handle qualifiers on typedef names yet!");
-    Result = TheSema.GetTypeFromParser(DS.getRepAsType());
+    Result = S.GetTypeFromParser(DS.getRepAsType());
     if (Result.isNull())
-      TheDeclarator.setInvalidType(true);
+      declarator.setInvalidType(true);
     else if (DeclSpec::ProtocolQualifierListTy PQ
                = DS.getProtocolQualifiers()) {
       if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
@@ -326,9 +752,9 @@
                                            DS.getNumProtocolQualifiers());
         Result = Context.getObjCObjectPointerType(Result);
       } else {
-        TheSema.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
+        S.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
           << DS.getSourceRange();
-        TheDeclarator.setInvalidType(true);
+        declarator.setInvalidType(true);
       }
     }
 
@@ -337,12 +763,11 @@
   }
   case DeclSpec::TST_typeofType:
     // FIXME: Preserve type source info.
-    Result = TheSema.GetTypeFromParser(DS.getRepAsType());
+    Result = S.GetTypeFromParser(DS.getRepAsType());
     assert(!Result.isNull() && "Didn't get a type for typeof?");
     if (!Result->isDependentType())
       if (const TagType *TT = Result->getAs<TagType>())
-        TheSema.DiagnoseUseOfDecl(TT->getDecl(), 
-                                  DS.getTypeSpecTypeLoc());
+        S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc());
     // TypeQuals handled by caller.
     Result = Context.getTypeOfType(Result);
     break;
@@ -350,10 +775,10 @@
     Expr *E = DS.getRepAsExpr();
     assert(E && "Didn't get an expression for typeof?");
     // TypeQuals handled by caller.
-    Result = TheSema.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
+    Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
     if (Result.isNull()) {
       Result = Context.IntTy;
-      TheDeclarator.setInvalidType(true);
+      declarator.setInvalidType(true);
     }
     break;
   }
@@ -361,10 +786,10 @@
     Expr *E = DS.getRepAsExpr();
     assert(E && "Didn't get an expression for decltype?");
     // TypeQuals handled by caller.
-    Result = TheSema.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
+    Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
     if (Result.isNull()) {
       Result = Context.IntTy;
-      TheDeclarator.setInvalidType(true);
+      declarator.setInvalidType(true);
     }
     break;
   }
@@ -376,14 +801,14 @@
 
   case DeclSpec::TST_error:
     Result = Context.IntTy;
-    TheDeclarator.setInvalidType(true);
+    declarator.setInvalidType(true);
     break;
   }
 
   // Handle complex types.
   if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
-    if (TheSema.getLangOptions().Freestanding)
-      TheSema.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
+    if (S.getLangOptions().Freestanding)
+      S.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
     Result = Context.getComplexType(Result);
   } else if (DS.isTypeAltiVecVector()) {
     unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result));
@@ -398,12 +823,18 @@
 
   // FIXME: Imaginary.
   if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary)
-    TheSema.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported);
+    S.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported);
 
-  // See if there are any attributes on the declspec that apply to the type (as
-  // opposed to the decl).
-  if (const AttributeList *AL = DS.getAttributes().getList())
-    ProcessTypeAttributeList(TheSema, Result, true, AL, Delayed);
+  // Before we process any type attributes, synthesize a block literal
+  // function declarator if necessary.
+  if (declarator.getContext() == Declarator::BlockLiteralContext)
+    maybeSynthesizeBlockSignature(state, Result);
+
+  // Apply any type attributes from the decl spec.  This may cause the
+  // list of type attributes to be temporarily saved while the type
+  // attributes are pushed around.
+  if (AttributeList *attrs = DS.getAttributes().getList())
+    processTypeAttrs(state, Result, true, attrs);
 
   // Apply const/volatile/restrict qualifiers to T.
   if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@@ -424,14 +855,14 @@
         // If we have a pointer or reference, the pointee must have an object
         // incomplete type.
         if (!EltTy->isIncompleteOrObjectType()) {
-          TheSema.Diag(DS.getRestrictSpecLoc(),
+          S.Diag(DS.getRestrictSpecLoc(),
                diag::err_typecheck_invalid_restrict_invalid_pointee)
             << EltTy << DS.getSourceRange();
           TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
         }
       } else {
-        TheSema.Diag(DS.getRestrictSpecLoc(),
-             diag::err_typecheck_invalid_restrict_not_pointer)
+        S.Diag(DS.getRestrictSpecLoc(),
+               diag::err_typecheck_invalid_restrict_not_pointer)
           << Result << DS.getSourceRange();
         TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
       }
@@ -452,7 +883,7 @@
                "Has CVR quals but not C, V, or R?");
         Loc = DS.getRestrictSpecLoc();
       }
-      TheSema.Diag(Loc, diag::warn_typecheck_function_qualifiers)
+      S.Diag(Loc, diag::warn_typecheck_function_qualifiers)
         << Result << DS.getSourceRange();
     }
 
@@ -981,15 +1412,15 @@
   // have a type.
   QualType T;
   TypeSourceInfo *ReturnTypeInfo = 0;
-  
-  llvm::SmallVector<DelayedAttribute,4> FnAttrsFromDeclSpec;
+
+  TypeProcessingState state(*this, D);
 
   switch (D.getName().getKind()) {
   case UnqualifiedId::IK_Identifier:
   case UnqualifiedId::IK_OperatorFunctionId:
   case UnqualifiedId::IK_LiteralOperatorId:
   case UnqualifiedId::IK_TemplateId:
-    T = ConvertDeclSpecToType(*this, D, FnAttrsFromDeclSpec);
+    T = ConvertDeclSpecToType(*this, state);
     
     if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
       TagDecl* Owned = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
@@ -1017,6 +1448,9 @@
     break;
   }
 
+  if (D.getAttributes())
+    distributeTypeAttrsFromDeclarator(state, T);
+
   // Check for auto functions and trailing return type and adjust the
   // return type accordingly.
   if (getLangOptions().CPlusPlus0x && D.isFunctionDeclarator()) {
@@ -1091,13 +1525,13 @@
   if (D.getIdentifier())
     Name = D.getIdentifier();
 
-  llvm::SmallVector<DelayedAttribute,4> FnAttrsFromPreviousChunk;
-
   // Walk the DeclTypeInfo, building the recursive type as we go.
   // DeclTypeInfos are ordered from the identifier out, which is
   // opposite of what we want :).
   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
-    DeclaratorChunk &DeclType = D.getTypeObject(e-i-1);
+    unsigned chunkIndex = e - i - 1;
+    state.setCurrentChunkIndex(chunkIndex);
+    DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
     switch (DeclType.Kind) {
     default: assert(0 && "Unknown decltype!");
     case DeclaratorChunk::Paren:
@@ -1129,6 +1563,7 @@
       T = BuildPointerType(T, DeclType.Loc, Name);
       if (DeclType.Ptr.TypeQuals)
         T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
+
       break;
     case DeclaratorChunk::Reference: {
       // Verify that we're not building a reference to pointer to function with
@@ -1352,12 +1787,6 @@
         T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI);
       }
 
-      // 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).
-      ProcessDelayedFnAttrs(*this, T, FnAttrsFromPreviousChunk);
-
       break;
     }
     case DeclaratorChunk::MemberPointer:
@@ -1418,11 +1847,9 @@
       T = Context.IntTy;
     }
 
-    DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk);
-
     // See if there are any attributes on this declarator chunk.
-    if (const AttributeList *AL = DeclType.getAttrs())
-      ProcessTypeAttributeList(*this, T, false, AL, FnAttrsFromPreviousChunk);
+    if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs()))
+      processTypeAttrs(state, T, false, attrs);
   }
 
   if (getLangOptions().CPlusPlus && T->isFunctionType()) {
@@ -1463,6 +1890,14 @@
     }
   }
 
+  // Apply any undistributed attributes from the declarator.
+  if (!T.isNull())
+    if (AttributeList *attrs = D.getAttributes())
+      processTypeAttrs(state, T, false, attrs);
+
+  // Diagnose any ignored type attributes.
+  if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T);
+
   // If there's a constexpr specifier, treat it as a top-level const.
   if (D.getDeclSpec().isConstexprSpecified()) {
     T.addConst();
@@ -1528,20 +1963,6 @@
     }
   }
   
-  // Process any function attributes we might have delayed from the
-  // declaration-specifiers.
-  ProcessDelayedFnAttrs(*this, T, FnAttrsFromDeclSpec);
-
-  // 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.
-  if (D.getContext() != Declarator::BlockLiteralContext)
-    if (const AttributeList *Attrs = D.getAttributes())
-      ProcessTypeAttributeList(*this, T, false, Attrs,
-                               FnAttrsFromPreviousChunk);
-
-  DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk);
-
   if (T.isNull())
     return Context.getNullTypeSourceInfo();
   else if (D.isInvalidType())
@@ -1923,41 +2344,53 @@
   Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
 }
 
-/// HandleObjCGCTypeAttribute - Process an objc's gc attribute on the
-/// specified type.  The attribute contains 1 argument, weak or strong.
-static void HandleObjCGCTypeAttribute(QualType &Type,
-                                      const AttributeList &Attr, Sema &S) {
-  if (Type.getObjCGCAttr() != Qualifiers::GCNone) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_multiple_objc_gc);
-    Attr.setInvalid();
-    return;
+/// handleObjCGCTypeAttr - Process the __attribute__((objc_gc)) type
+/// attribute on the specified type.  Returns true to indicate that
+/// the attribute was handled, false to indicate that the type does
+/// not permit the attribute.
+static bool handleObjCGCTypeAttr(TypeProcessingState &state,
+                                 AttributeList &attr,
+                                 QualType &type) {
+  Sema &S = state.getSema();
+
+  // Delay if this isn't some kind of pointer.
+  if (!type->isPointerType() &&
+      !type->isObjCObjectPointerType() &&
+      !type->isBlockPointerType())
+    return false;
+
+  if (type.getObjCGCAttr() != Qualifiers::GCNone) {
+    S.Diag(attr.getLoc(), diag::err_attribute_multiple_objc_gc);
+    attr.setInvalid();
+    return true;
   }
 
   // Check the attribute arguments.
-  if (!Attr.getParameterName()) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+  if (!attr.getParameterName()) {
+    S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
       << "objc_gc" << 1;
-    Attr.setInvalid();
-    return;
+    attr.setInvalid();
+    return true;
   }
   Qualifiers::GC GCAttr;
-  if (Attr.getNumArgs() != 0) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
-    Attr.setInvalid();
-    return;
+  if (attr.getNumArgs() != 0) {
+    S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    attr.setInvalid();
+    return true;
   }
-  if (Attr.getParameterName()->isStr("weak"))
+  if (attr.getParameterName()->isStr("weak"))
     GCAttr = Qualifiers::Weak;
-  else if (Attr.getParameterName()->isStr("strong"))
+  else if (attr.getParameterName()->isStr("strong"))
     GCAttr = Qualifiers::Strong;
   else {
-    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
-      << "objc_gc" << Attr.getParameterName();
-    Attr.setInvalid();
-    return;
+    S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
+      << "objc_gc" << attr.getParameterName();
+    attr.setInvalid();
+    return true;
   }
 
-  Type = S.Context.getObjCGCQualType(Type, GCAttr);
+  type = S.Context.getObjCGCQualType(type, GCAttr);
+  return true;
 }
 
 namespace {
@@ -2091,127 +2524,90 @@
   };
 }
 
-/// Process an individual function attribute.  Returns true if the
-/// attribute does not make sense to apply to this type.
-static bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
-  FunctionTypeUnwrapper Unwrapped(S, Type);
-
-  if (Attr.getKind() == AttributeList::AT_noreturn) {
-    // Complain immediately if the arg count is wrong.
-    if (Attr.getNumArgs() != 0) {
-      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
-      Attr.setInvalid();
-      return false;
-    }
-
-    // Delay if this is not a function type.
-    if (!Unwrapped.isFunctionType())
-      return true;
+/// Process an individual function attribute.  Returns true to
+/// indicate that the attribute was handled, false if it wasn't.
+static bool handleFunctionTypeAttr(TypeProcessingState &state,
+                                   AttributeList &attr,
+                                   QualType &type) {
+  Sema &S = state.getSema();
 
-    // Otherwise we can process right away.
-    FunctionType::ExtInfo EI = Unwrapped.get()->getExtInfo().withNoReturn(true);
-    Type = Unwrapped.wrap(S, S.Context.adjustFunctionType(Unwrapped.get(), EI));
-    return false;
-  }
+  FunctionTypeUnwrapper unwrapped(S, type);
 
-  if (Attr.getKind() == AttributeList::AT_regparm) {
-    // The warning is emitted elsewhere
-    if (Attr.getNumArgs() != 1) {
-      return false;
-    }
+  if (attr.getKind() == AttributeList::AT_noreturn) {
+    if (S.CheckNoReturnAttr(attr))
+      return true;
 
     // Delay if this is not a function type.
-    if (!Unwrapped.isFunctionType())
-      return true;
+    if (!unwrapped.isFunctionType())
+      return false;
 
     // Otherwise we can process right away.
-    Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
-    llvm::APSInt NumParams(32);
-
-    // The warning is emitted elsewhere
-    if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() ||
-        !NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context))
-      return false;
+    FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withNoReturn(true);
+    type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+    return true;
+  }
 
-    if (S.Context.Target.getRegParmMax() == 0) {
-      S.Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
-        << NumParamsExpr->getSourceRange();
-      Attr.setInvalid();
-      return false;
-    }
+  if (attr.getKind() == AttributeList::AT_regparm) {
+    unsigned value;
+    if (S.CheckRegparmAttr(attr, value))
+      return true;
 
-    if (NumParams.getLimitedValue(255) > S.Context.Target.getRegParmMax()) {
-      S.Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
-        << S.Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange();
-      Attr.setInvalid();
+    // Delay if this is not a function type.
+    if (!unwrapped.isFunctionType())
       return false;
-    }
 
     FunctionType::ExtInfo EI = 
-      Unwrapped.get()->getExtInfo().withRegParm(NumParams.getZExtValue());
-    Type = Unwrapped.wrap(S, S.Context.adjustFunctionType(Unwrapped.get(), EI));
-    return false;
+      unwrapped.get()->getExtInfo().withRegParm(value);
+    type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+    return true;
   }
 
   // Otherwise, a calling convention.
-  if (Attr.getNumArgs() != 0) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
-    Attr.setInvalid();
-    return false;
-  }
+  CallingConv CC;
+  if (S.CheckCallingConvAttr(attr, CC))
+    return true;
 
   // Delay if the type didn't work out to a function.
-  if (!Unwrapped.isFunctionType()) return true;
+  if (!unwrapped.isFunctionType()) return false;
 
-  // TODO: diagnose uses of these conventions on the wrong target.
-  CallingConv CC;
-  switch (Attr.getKind()) {
-  case AttributeList::AT_cdecl: CC = CC_C; break;
-  case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
-  case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
-  case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break;
-  case AttributeList::AT_pascal: CC = CC_X86Pascal; break;
-  default: llvm_unreachable("unexpected attribute kind"); return false;
-  }
-
-  const FunctionType *Fn = Unwrapped.get();
-  CallingConv CCOld = Fn->getCallConv();
+  const FunctionType *fn = unwrapped.get();
+  CallingConv CCOld = fn->getCallConv();
   if (S.Context.getCanonicalCallConv(CC) ==
       S.Context.getCanonicalCallConv(CCOld)) {
-    Attr.setInvalid();
-    return false;
+    attr.setInvalid();
+    return true;
   }
 
   if (CCOld != CC_Default) {
     // Should we diagnose reapplications of the same convention?
-    S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+    S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
       << FunctionType::getNameForCallConv(CC)
       << FunctionType::getNameForCallConv(CCOld);
-    Attr.setInvalid();
-    return false;
+    attr.setInvalid();
+    return true;
   }
 
   // Diagnose the use of X86 fastcall on varargs or unprototyped functions.
   if (CC == CC_X86FastCall) {
-    if (isa<FunctionNoProtoType>(Fn)) {
-      S.Diag(Attr.getLoc(), diag::err_cconv_knr)
+    if (isa<FunctionNoProtoType>(fn)) {
+      S.Diag(attr.getLoc(), diag::err_cconv_knr)
         << FunctionType::getNameForCallConv(CC);
-      Attr.setInvalid();
-      return false;
+      attr.setInvalid();
+      return true;
     }
 
-    const FunctionProtoType *FnP = cast<FunctionProtoType>(Fn);
+    const FunctionProtoType *FnP = cast<FunctionProtoType>(fn);
     if (FnP->isVariadic()) {
-      S.Diag(Attr.getLoc(), diag::err_cconv_varargs)
+      S.Diag(attr.getLoc(), diag::err_cconv_varargs)
         << FunctionType::getNameForCallConv(CC);
-      Attr.setInvalid();
-      return false;
+      attr.setInvalid();
+      return true;
     }
   }
 
-  FunctionType::ExtInfo EI = Unwrapped.get()->getExtInfo().withCallingConv(CC);
-  Type = Unwrapped.wrap(S, S.Context.adjustFunctionType(Unwrapped.get(), EI));
-  return false;
+  FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
+  type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+  return true;
 }
 
 /// HandleVectorSizeAttribute - this attribute is only applicable to integral
@@ -2327,55 +2723,59 @@
   CurType = S.Context.getVectorType(CurType, numElts, VecKind);
 }
 
-void ProcessTypeAttributeList(Sema &S, QualType &Result,
-                              bool IsDeclSpec, const AttributeList *AL,
-                              DelayedAttributeSet &FnAttrs) {
+static void processTypeAttrs(TypeProcessingState &state, QualType &type,
+                             bool isDeclSpec, AttributeList *attrs) {
   // Scan through and apply attributes to this type where it makes sense.  Some
   // attributes (such as __address_space__, __vector_size__, etc) apply to the
   // type, but others can be present in the type specifiers even though they
   // apply to the decl.  Here we apply type attributes and ignore the rest.
-  for (; AL; AL = AL->getNext()) {
+
+  AttributeList *next;
+  do {
+    AttributeList &attr = *attrs;
+    next = attr.getNext();
+
     // Skip attributes that were marked to be invalid.
-    if (AL->isInvalid())
+    if (attr.isInvalid())
       continue;
 
     // If this is an attribute we can handle, do so now,
     // otherwise, add it to the FnAttrs list for rechaining.
-    switch (AL->getKind()) {
+    switch (attr.getKind()) {
     default: break;
 
     case AttributeList::AT_address_space:
-      HandleAddressSpaceTypeAttribute(Result, *AL, S);
+      HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
       break;
-    case AttributeList::AT_objc_gc:
-      HandleObjCGCTypeAttribute(Result, *AL, S);
+    OBJC_POINTER_TYPE_ATTRS_CASELIST:
+      if (!handleObjCPointerTypeAttr(state, attr, type))
+        distributeObjCPointerTypeAttr(state, attr, type);
       break;
     case AttributeList::AT_vector_size:
-      HandleVectorSizeAttr(Result, *AL, S);
+      HandleVectorSizeAttr(type, attr, state.getSema());
       break;
     case AttributeList::AT_neon_vector_type:
-      HandleNeonVectorTypeAttr(Result, *AL, S, VectorType::NeonVector,
-                               "neon_vector_type");
+      HandleNeonVectorTypeAttr(type, attr, state.getSema(),
+                               VectorType::NeonVector, "neon_vector_type");
       break;
     case AttributeList::AT_neon_polyvector_type:
-      HandleNeonVectorTypeAttr(Result, *AL, S, VectorType::NeonPolyVector,
+      HandleNeonVectorTypeAttr(type, attr, state.getSema(),
+                               VectorType::NeonPolyVector,
                                "neon_polyvector_type");
       break;
 
-    case AttributeList::AT_noreturn:
-    case AttributeList::AT_cdecl:
-    case AttributeList::AT_fastcall:
-    case AttributeList::AT_stdcall:
-    case AttributeList::AT_thiscall:
-    case AttributeList::AT_pascal:
-    case AttributeList::AT_regparm:
-      // Don't process these on the DeclSpec.
-      if (IsDeclSpec ||
-          ProcessFnAttr(S, Result, *AL))
-        FnAttrs.push_back(DelayedAttribute(AL, Result));
+    FUNCTION_TYPE_ATTRS_CASELIST:
+      // Never process function type attributes as part of the
+      // declaration-specifiers.
+      if (isDeclSpec)
+        distributeFunctionTypeAttrFromDeclSpec(state, attr, type);
+
+      // Otherwise, handle the possible delays.
+      else if (!handleFunctionTypeAttr(state, attr, type))
+        distributeFunctionTypeAttr(state, attr, type);
       break;
     }
-  }
+  } while ((attrs = next));
 }
 
 /// @brief Ensure that the type T is a complete type.

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Jan  5 06:14:39 2011
@@ -6748,15 +6748,7 @@
     else if (BExprResultType != SemaRef.Context.DependentTy)
       CurBlock->ReturnType = getDerived().TransformType(BExprResultType);
   }
-    
-  // Transform the body
-  StmtResult Body = getDerived().TransformStmt(E->getBody());
-  if (Body.isInvalid())
-    return ExprError();
-  // Set the parameters on the block decl.
-  if (!Params.empty())
-    CurBlock->TheDecl->setParams(Params.data(), Params.size());
-    
+
   QualType FunctionType = getDerived().RebuildFunctionProtoType(
                                                         CurBlock->ReturnType,
                                                         ParamTypes.data(),
@@ -6764,8 +6756,17 @@
                                                         BD->isVariadic(),
                                                         0,
                                                BExprFunctionType->getExtInfo());
-  
   CurBlock->FunctionType = FunctionType;
+
+  // Set the parameters on the block decl.
+  if (!Params.empty())
+    CurBlock->TheDecl->setParams(Params.data(), Params.size());
+    
+  // Transform the body
+  StmtResult Body = getDerived().TransformStmt(E->getBody());
+  if (Body.isInvalid())
+    return ExprError();
+
   return SemaRef.ActOnBlockStmtExpr(CaretLoc, Body.get(), /*Scope=*/0);
 }
 

Modified: cfe/trunk/test/Sema/block-return.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/block-return.c?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/test/Sema/block-return.c (original)
+++ cfe/trunk/test/Sema/block-return.c Wed Jan  5 06:14:39 2011
@@ -97,7 +97,7 @@
 }
 
 int (*funcptr3[5])(long);
-int sz8 = sizeof(^int (*[5])(long) {return funcptr3;}); // expected-error {{block declared as returning an array}}
+int sz8 = sizeof(^int (*[5])(long) {return funcptr3;}); // expected-error {{function cannot return array type}} expected-warning {{incompatible pointer to integer conversion}}
 
 void foo6() {
   int (^b)(int) __attribute__((noreturn));

Modified: cfe/trunk/test/Sema/stdcall-fastcall.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/stdcall-fastcall.c?rev=122871&r1=122870&r2=122871&view=diff
==============================================================================
--- cfe/trunk/test/Sema/stdcall-fastcall.c (original)
+++ cfe/trunk/test/Sema/stdcall-fastcall.c Wed Jan  5 06:14:39 2011
@@ -5,6 +5,6 @@
 int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' only applies to function types; type here is 'int'}}
 
 // Different CC qualifiers are not compatible
-void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{stdcall and fastcall attributes are not compatible}}
+void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{fastcall and stdcall attributes are not compatible}}
 void __attribute__((stdcall)) foo4(); // expected-note{{previous declaration is here}}
 void __attribute__((fastcall)) foo4(void); // expected-error{{function declared 'fastcall' here was previously declared 'stdcall'}}





More information about the cfe-commits mailing list