<div dir="ltr">On Wed, Aug 21, 2013 at 4:45 AM, Benjamin Kramer <span dir="ltr"><<a href="mailto:benny.kra@googlemail.com" target="_blank">benny.kra@googlemail.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: d0k<br>
Date: Wed Aug 21 06:45:27 2013<br>
New Revision: 188900<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=188900&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=188900&view=rev</a><br>
Log:<br>
Sema: Use the right type for PredefinedExpr when it's in a lambda.<br>
<br>
1. We now print the return type of lambdas and return type deduced functions<br>
as "auto". Trailing return types with decltype print the underlying type.<br>
2. Use the lambda or block scope for the PredefinedExpr type instead of the<br>
parent function. This fixes PR16946, a strange mismatch between type of the<br>
expression and the actual result.<br>
3. Verify the type in CodeGen.<br>
4. The type for blocks is still wrong. They are numbered and the name is not<br>
known until CodeGen.<br>
<br>
Added:<br>
    cfe/trunk/test/SemaCXX/predefined-expr.cpp<br>
Modified:<br>
    cfe/trunk/lib/AST/Expr.cpp<br>
    cfe/trunk/lib/CodeGen/CGExpr.cpp<br>
    cfe/trunk/lib/Sema/SemaExpr.cpp<br>
<br>
Modified: cfe/trunk/lib/AST/Expr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=188900&r1=188899&r2=188900&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=188900&r1=188899&r2=188900&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/Expr.cpp (original)<br>
+++ cfe/trunk/lib/AST/Expr.cpp Wed Aug 21 06:45:27 2013<br>
@@ -585,7 +585,18 @@ std::string PredefinedExpr::ComputeName(<br>
<br>
     POut.flush();<br>
<br>
-    if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))<br>
+    // Print "auto" for all deduced return types. This includes C++1y return<br>
+    // type deduction and lambdas. For trailing return types resolve the<br>
+    // decltype expression. Otherwise print the real type when this is<br>
+    // not a constructor or destructor.<br>
+    if ((isa<CXXMethodDecl>(FD) &&<br>
+         cast<CXXMethodDecl>(FD)->getParent()->isLambda()) ||<br>
+        (FT && FT->getResultType()->getAs<AutoType>()))<br>
+      Proto = "auto " + Proto;<br></blockquote><div><br></div><div>This looks wrong in a couple of ways:</div><div><br></div><div> * For a lambda with an explicitly-specified return type, we'll print 'auto' anyway</div>
<div> * For a function with a return type of, say, "auto *", we'll not hit this special case</div><div><br></div><div>Instead, you should use the declared return type (the type as written, from the TypeSourceInfo). It looks like we'll unhelpfully put 'DependentTy' there if no return type is specified; perhaps we should put an undeduced 'auto' type there instead.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    else if (FT && FT->getResultType()->getAs<DecltypeType>())<br>
+      FT->getResultType()->getAs<DecltypeType>()->getUnderlyingType()<br>
+          .getAsStringInternal(Proto, Policy);<br></blockquote><div><br></div><div>Why perform this partial desugaring?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+    else if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))<br></blockquote><div><br></div><div>What about conversion operators? They also have no declared return type. (And 'operator auto()' in C++14 is another case we need to handle carefully.)</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
       AFT->getResultType().getAsStringInternal(Proto, Policy);<br>
<br>
     Out << Proto;<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=188900&r1=188899&r2=188900&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=188900&r1=188899&r2=188900&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Wed Aug 21 06:45:27 2013<br>
@@ -1937,7 +1937,7 @@ LValue CodeGenFunction::EmitPredefinedLV<br>
   case PredefinedExpr::Function:<br>
   case PredefinedExpr::LFunction:<br>
   case PredefinedExpr::PrettyFunction: {<br>
-    unsigned IdentType = E->getIdentType();<br>
+    PredefinedExpr::IdentType IdentType = E->getIdentType();<br>
     std::string GlobalVarName;<br>
<br>
     switch (IdentType) {<br>
@@ -1961,17 +1961,24 @@ LValue CodeGenFunction::EmitPredefinedLV<br>
       FnName = FnName.substr(1);<br>
     GlobalVarName += FnName;<br>
<br>
+    // If this is outside of a function use the top level decl.<br>
     const Decl *CurDecl = CurCodeDecl;<br>
-    if (CurDecl == 0)<br>
+    if (CurDecl == 0 || isa<VarDecl>(CurDecl))<br>
       CurDecl = getContext().getTranslationUnitDecl();<br>
<br>
-    std::string FunctionName =<br>
-        (isa<BlockDecl>(CurDecl)<br>
-         ? FnName.str()<br>
-         : PredefinedExpr::ComputeName((PredefinedExpr::IdentType)IdentType,<br>
-                                       CurDecl));<br>
+    const Type *ElemType = E->getType()->getArrayElementTypeNoTypeQual();<br>
+    std::string FunctionName;<br>
+    if (isa<BlockDecl>(CurDecl)) {<br>
+      // Blocks use the mangled function name.<br>
+      // FIXME: ComputeName should handle blocks.<br>
+      FunctionName = FnName.str();<br>
+    } else {<br>
+      FunctionName = PredefinedExpr::ComputeName(IdentType, CurDecl);<br>
+      assert(cast<ConstantArrayType>(E->getType())->getSize() - 1 ==<br>
+                 FunctionName.size() &&<br>
+             "Computed __func__ length differs from type!");<br>
+    }<br>
<br>
-    const Type* ElemType = E->getType()->getArrayElementTypeNoTypeQual();<br>
     llvm::Constant *C;<br>
     if (ElemType->isWideCharType()) {<br>
       SmallString<32> RawChars;<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=188900&r1=188899&r2=188900&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=188900&r1=188899&r2=188900&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Aug 21 06:45:27 2013<br>
@@ -2759,14 +2759,14 @@ ExprResult Sema::ActOnPredefinedExpr(Sou<br>
   // Pre-defined identifiers are of type char[x], where x is the length of the<br>
   // string.<br>
<br>
-  Decl *currentDecl = getCurFunctionOrMethodDecl();<br>
-  // Blocks and lambdas can occur at global scope. Don't emit a warning.<br>
-  if (!currentDecl) {<br>
-    if (const BlockScopeInfo *BSI = getCurBlock())<br>
-      currentDecl = BSI->TheDecl;<br>
-    else if (const LambdaScopeInfo *LSI = getCurLambda())<br>
-      currentDecl = LSI->CallOperator;<br>
-  }<br>
+  // Pick the current block, lambda or function.<br>
+  Decl *currentDecl;<br>
+  if (const BlockScopeInfo *BSI = getCurBlock())<br>
+    currentDecl = BSI->TheDecl;<br>
+  else if (const LambdaScopeInfo *LSI = getCurLambda())<br>
+    currentDecl = LSI->CallOperator;<br>
+  else<br>
+    currentDecl = getCurFunctionOrMethodDecl();<br></blockquote><div><br></div><div>I don't think this correctly handles the case where FunctionScopes.back() is an SK_CapturedRegion (inside, say, a lambda).</div><div>
 </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
   if (!currentDecl) {<br>
     Diag(Loc, diag::ext_predef_outside_function);<br>
<br>
Added: cfe/trunk/test/SemaCXX/predefined-expr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/predefined-expr.cpp?rev=188900&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/predefined-expr.cpp?rev=188900&view=auto</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/predefined-expr.cpp (added)<br>
+++ cfe/trunk/test/SemaCXX/predefined-expr.cpp Wed Aug 21 06:45:27 2013<br>
@@ -0,0 +1,40 @@<br>
+// RUN: %clang_cc1 -std=c++1y -fblocks -fsyntax-only -verify %s<br>
+// PR16946<br>
+// expected-no-diagnostics<br>
+<br>
+auto foo() {<br>
+  static_assert(sizeof(__func__) == 4, "foo");<br>
+  static_assert(sizeof(__FUNCTION__) == 4, "foo");<br>
+  static_assert(sizeof(__PRETTY_FUNCTION__) == 11, "auto foo()");<br>
+  return 0;<br>
+}<br>
+<br>
+auto bar() -> decltype(42) {<br>
+  static_assert(sizeof(__func__) == 4, "bar");<br>
+  static_assert(sizeof(__FUNCTION__) == 4, "bar");<br>
+  static_assert(sizeof(__PRETTY_FUNCTION__) == 10, "int bar()");<br>
+  return 0;<br>
+}<br>
+<br>
+int main() {<br>
+  static_assert(sizeof(__func__) == 5, "main");<br>
+  static_assert(sizeof(__FUNCTION__) == 5, "main");<br>
+  static_assert(sizeof(__PRETTY_FUNCTION__) == 11, "int main()");<br>
+<br>
+  []() {<br>
+    static_assert(sizeof(__func__) == 11, "operator()");<br>
+    static_assert(sizeof(__FUNCTION__) == 11, "operator()");<br>
+    static_assert(sizeof(__PRETTY_FUNCTION__) == 51,<br>
+                  "auto main()::<anonymous class>::operator()() const");<br>
+    return 0;<br>
+  }<br>
+  ();<br>
+<br>
+  ^{<br>
+    // FIXME: This is obviously wrong.<br>
+    static_assert(sizeof(__func__) == 1, "__main_block_invoke");<br>
+    static_assert(sizeof(__FUNCTION__) == 1, "__main_block_invoke");<br>
+    static_assert(sizeof(__PRETTY_FUNCTION__) == 1, "__main_block_invoke");<br>
+  }<br>
+  ();<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>