Use QualType to represent block's implicit return type as
to not lose its 'const/volatile' qualifier.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73795 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index bb9fa4b..23bab23 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -102,7 +102,7 @@
   
   /// ReturnType - This will get set to block result type, by looking at
   /// return types, if any, in the block body.
-  Type *ReturnType;
+  QualType ReturnType;
   
   /// LabelMap - This is a mapping from label identifiers to the LabelStmt for
   /// it (which acts like the label decl in some ways).  Forward referenced
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7e82783..de56819 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1129,10 +1129,13 @@
     // The BlocksAttr indicates the variable is bound by-reference.
     if (VD->getAttr<BlocksAttr>(Context))
       return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, true));
-
+    // This is to record that a 'const' was actually synthesize and added.
+    bool constAdded = !ExprTy.isConstQualified();
     // Variable will be bound by-copy, make it const within the closure.
+    
     ExprTy.addConst();
-    return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false));
+    return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false, 
+                                                constAdded));
   }
   // If this reference is not in a block or if the referenced variable is
   // within the block, create a normal DeclRefExpr.
@@ -5111,7 +5114,7 @@
   BSI->PrevBlockInfo = CurBlock;
   CurBlock = BSI;
 
-  BSI->ReturnType = 0;
+  BSI->ReturnType = QualType();
   BSI->TheScope = BlockScope;
   BSI->hasBlockDeclRefExprs = false;
   BSI->SavedFunctionNeedsScopeChecking = CurFunctionNeedsScopeChecking;
@@ -5206,7 +5209,7 @@
     Diag(ParamInfo.getSourceRange().getBegin(),
          diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
   } else if (!RetTy->isDependentType())
-    CurBlock->ReturnType = RetTy.getTypePtr();
+    CurBlock->ReturnType = RetTy;
 }
 
 /// ActOnBlockError - If there is an error parsing a block, this callback
@@ -5240,8 +5243,8 @@
   CurBlock = CurBlock->PrevBlockInfo;
 
   QualType RetTy = Context.VoidTy;
-  if (BSI->ReturnType)
-    RetTy = QualType(BSI->ReturnType, 0);
+  if (!BSI->ReturnType.isNull())
+    RetTy = BSI->ReturnType;
 
   llvm::SmallVector<QualType, 8> ArgTypes;
   for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i)
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 7797e27..914839c 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -748,16 +748,23 @@
 Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
   // If this is the first return we've seen in the block, infer the type of
   // the block from it.
-  if (CurBlock->ReturnType == 0) {
+  if (CurBlock->ReturnType.isNull()) {
     if (RetValExp) {
       // Don't call UsualUnaryConversions(), since we don't want to do
       // integer promotions here.
       DefaultFunctionArrayConversion(RetValExp);
-      CurBlock->ReturnType = RetValExp->getType().getTypePtr();
+      CurBlock->ReturnType = RetValExp->getType();
+      if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
+        // We have to remove a 'const' added to copied-in variable which was
+        // part of the implementation spec. and not the actual qualifier for
+        // the variable.
+        if (CDRE->isConstQualAdded())
+           CurBlock->ReturnType.removeConst();
+      }
     } else
-      CurBlock->ReturnType = Context.VoidTy.getTypePtr();
+      CurBlock->ReturnType = Context.VoidTy;
   }
-  QualType FnRetType = QualType(CurBlock->ReturnType, 0);
+  QualType FnRetType = CurBlock->ReturnType;
 
   if (CurBlock->TheDecl->hasAttr<NoReturnAttr>(Context)) {
     Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr)