<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Dec 3, 2011, at 9:47 AM, Fariborz Jahanian wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Author: fjahanian<br>Date: Sat Dec 3 11:47:53 2011<br>New Revision: 145774<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=145774&view=rev">http://llvm.org/viewvc/llvm-project?rev=145774&view=rev</a><br>Log:<br>If block literal return type is not specified, return type of the block is <br>inferred from return types. All the return statements have to agree about the type.<br>// <a href="rdar://10466373">rdar://10466373</a><br><br>Added:<br> cfe/trunk/test/Sema/block-explicit-noreturn-type.c<br>Modified:<br> cfe/trunk/include/clang/AST/Decl.h<br> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br> cfe/trunk/lib/Sema/SemaExpr.cpp<br> cfe/trunk/lib/Sema/SemaStmt.cpp<br> cfe/trunk/lib/Sema/TreeTransform.h<br> cfe/trunk/test/Sema/block-return.c<br> cfe/trunk/test/SemaCXX/instantiate-blocks.cpp<br><br>Modified: cfe/trunk/include/clang/AST/Decl.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=145774&r1=145773&r2=145774&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=145774&r1=145773&r2=145774&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/AST/Decl.h (original)<br>+++ cfe/trunk/include/clang/AST/Decl.h Sat Dec 3 11:47:53 2011<br>@@ -2981,6 +2981,7 @@<br> // FIXME: This can be packed into the bitfields in Decl.<br> bool IsVariadic : 1;<br> bool CapturesCXXThis : 1;<br>+ bool BlockMissingReturnType : 1;<br> /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal<br> /// parameters of this function. This is null if a prototype or if there are<br> /// no formals.<br>@@ -2997,6 +2998,7 @@<br> BlockDecl(DeclContext *DC, SourceLocation CaretLoc)<br> : Decl(Block, DC, CaretLoc), DeclContext(Block),<br> IsVariadic(false), CapturesCXXThis(false),<br>+ BlockMissingReturnType(true),<br> ParamInfo(0), NumParams(0), Body(0),<br> SignatureAsWritten(0), Captures(0), NumCaptures(0) {}<br><br>@@ -3054,6 +3056,8 @@<br> capture_const_iterator capture_end() const { return Captures + NumCaptures; }<br><br> bool capturesCXXThis() const { return CapturesCXXThis; }<br>+ bool blockMissingReturnType() const { return BlockMissingReturnType; }<br>+ void setBlockMissingReturnType(bool val) { BlockMissingReturnType = val; }<br><br> bool capturesVariable(const VarDecl *var) const;<br><br><br>Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=145774&r1=145773&r2=145774&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=145774&r1=145773&r2=145774&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Dec 3 11:47:53 2011<br>@@ -4061,6 +4061,9 @@<br> "volatile and restrict|const, volatile, and restrict}5 vs "<br> "%select{none|const|restrict|const and restrict|volatile|const and volatile|"<br> "volatile and restrict|const, volatile, and restrict}6)}4">;<br>+def err_typecheck_missing_return_type_incompatible : Error<<br>+ "return type %0 must match previous return type %1 when block"<br>+ " literal has unspecified explicit return type">;<br><br> def warn_incompatible_qualified_id : Warning<<br> "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"<br><br>Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=145774&r1=145773&r2=145774&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=145774&r1=145773&r2=145774&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Dec 3 11:47:53 2011<br>@@ -8715,8 +8715,10 @@<br> // return type. TODO: what should we do with declarators like:<br> // ^ * { ... }<br> // If the answer is "apply template argument deduction"....<br>- if (RetTy != Context.DependentTy)<br>+ if (RetTy != Context.DependentTy) {<br> CurBlock->ReturnType = RetTy;<br>+ CurBlock->TheDecl->setBlockMissingReturnType(false);<br>+ }<br><br> // Push block parameters from the declarator if we had them.<br> SmallVector<ParmVarDecl*, 8> Params;<br><br>Modified: cfe/trunk/lib/Sema/SemaStmt.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=145774&r1=145773&r2=145774&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=145774&r1=145773&r2=145774&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaStmt.cpp Sat Dec 3 11:47:53 2011<br>@@ -1809,6 +1809,16 @@<br> } else if (!RetValExp) {<br> return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr));<br> } else if (!RetValExp->isTypeDependent()) {<br>+ if (CurBlock->TheDecl->blockMissingReturnType()) {<br>+ // when block's return type is not specified, all return types<br>+ // must strictly match.<br>+ if (Context.getCanonicalType(FnRetType) != <br>+ Context.getCanonicalType(RetValExp->getType())) {<br></div></blockquote><div><br></div><div>Context.hasSameType(FnRetType, RetValExp->getType()) would be a little cleaner. </div><br></div><div>More importantly, I think this is the wrong place for this check, because the code isn't performing function or array lvalue conversions before checking the type of the return expression. I suggest making sure that blocks with inferred return types always go into this code:</div><div><br></div><div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> <span style="color: #b930a1">if</span> (CurBlock-><span style="color: #518187">ReturnType</span>.<span style="color: #33595d">isNull</span>()) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> <span style="color: #b930a1">if</span> (RetValExp) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; color: rgb(0, 131, 17); "><span style="color: #000000"> </span>// Don't call UsualUnaryConversions(), since we don't want to do</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; color: rgb(0, 131, 17); "><span style="color: #000000"> </span>// integer promotions here.</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; color: rgb(51, 89, 93); "><span style="color: #000000"> </span><span style="color: #518187">ExprResult</span><span style="color: #000000"> Result = </span>DefaultFunctionArrayLvalueConversion<span style="color: #000000">(RetValExp);</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> <span style="color: #b930a1">if</span> (Result.<span style="color: #33595d">isInvalid</span>())</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> <span style="color: #b930a1">return</span> <span style="color: #33595d">StmtError</span>();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> RetValExp = Result.<span style="color: #33595d">take</span>();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; min-height: 13px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> <span style="color: #b930a1">if</span> (!RetValExp-><span style="color: #33595d">isTypeDependent</span>()) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> CurBlock-><span style="color: #518187">ReturnType</span> = RetValExp-><span style="color: #33595d">getType</span>();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> <span style="color: #b930a1">if</span> (<span style="color: #518187">BlockDeclRefExpr</span> *CDRE = <span style="color: #3e217f">dyn_cast</span><<span style="color: #518187">BlockDeclRefExpr</span>>(RetValExp)) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; color: rgb(0, 131, 17); "><span style="color: #000000"> </span>// We have to remove a 'const' added to copied-in variable which was</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; color: rgb(0, 131, 17); "><span style="color: #000000"> </span>// part of the implementation spec. and not the actual qualifier for</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; color: rgb(0, 131, 17); "><span style="color: #000000"> </span>// the variable.</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> <span style="color: #b930a1">if</span> (CDRE-><span style="color: #33595d">isConstQualAdded</span>())</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> CurBlock-><span style="color: #518187">ReturnType</span>.<span style="color: #33595d">removeLocalConst</span>(); <span style="color: #008311">// FIXME: local???</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> } <span style="color: #b930a1">else</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> CurBlock-><span style="color: #518187">ReturnType</span> = <span style="color: #33595d">Context</span>.<span style="color: #33595d">DependentTy</span>;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> } <span style="color: #b930a1">else</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> CurBlock-><span style="color: #518187">ReturnType</span> = <span style="color: #33595d">Context</span>.<span style="color: #33595d">VoidTy</span>;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 11px/normal Menlo; "> }</div><div><br></div><div>so they all get the same adjustments before checking against previously-deduced return types.</div></div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>- Doug</div><br></body></html>