<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>