<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Feb 25, 2014 at 1:20 PM, Benjamin Kramer <span dir="ltr"><<a href="mailto:benny.kra@gmail.com" target="_blank">benny.kra@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Tue, Feb 25, 2014 at 8:58 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>> wrote:<br>

> On Tue, Feb 25, 2014 at 9:26 AM, Benjamin Kramer <<a href="mailto:benny.kra@googlemail.com">benny.kra@googlemail.com</a>><br>
> wrote:<br>
>><br>
>> Author: d0k<br>
>> Date: Tue Feb 25 11:26:26 2014<br>
>> New Revision: 202167<br>
>><br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=202167&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=202167&view=rev</a><br>
>> Log:<br>
>> Pretty Printer: Fix printing of conversion operator decls and calls.<br>
>><br>
>> - Don't emit anything when we encounter a call to a conversion operator.<br>
>>     "bar(a & b)" instead of "bar(a & b.operator int())"<br>
>>   This preserves the semantics and is still idempotent if we print the AST<br>
>> multiple times.<br>
>><br>
>> - Properly print declarations of conversion operators.<br>
>>     "explicit operator bool();" instead of "bool operator _Bool();"<br>
>><br>
>> PR18776.<br>
>><br>
>> Modified:<br>
>>     cfe/trunk/lib/AST/DeclPrinter.cpp<br>
>>     cfe/trunk/lib/AST/DeclarationName.cpp<br>
>>     cfe/trunk/lib/AST/StmtPrinter.cpp<br>
>>     cfe/trunk/test/SemaCXX/ast-print.cpp<br>
>><br>
>> Modified: cfe/trunk/lib/AST/DeclPrinter.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=202167&r1=202166&r2=202167&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=202167&r1=202166&r2=202167&view=diff</a><br>

>><br>
>> ==============================================================================<br>
>> --- cfe/trunk/lib/AST/DeclPrinter.cpp (original)<br>
>> +++ cfe/trunk/lib/AST/DeclPrinter.cpp Tue Feb 25 11:26:26 2014<br>
>> @@ -385,6 +385,7 @@ void DeclPrinter::VisitEnumConstantDecl(<br>
>><br>
>>  void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {<br>
>>    CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);<br>
>> +  CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);<br>
>>    if (!Policy.SuppressSpecifiers) {<br>
>>      switch (D->getStorageClass()) {<br>
>>      case SC_None: break;<br>
>> @@ -398,7 +399,8 @@ void DeclPrinter::VisitFunctionDecl(Func<br>
>>      if (D->isInlineSpecified())  Out << "inline ";<br>
>>      if (D->isVirtualAsWritten()) Out << "virtual ";<br>
>>      if (D->isModulePrivate())    Out << "__module_private__ ";<br>
>> -    if (CDecl && CDecl->isExplicitSpecified())<br>
>> +    if ((CDecl && CDecl->isExplicitSpecified()) ||<br>
>> +        (ConversionDecl && ConversionDecl->isExplicit()))<br>
>>        Out << "explicit ";<br>
>>    }<br>
>><br>
>> @@ -536,15 +538,15 @@ void DeclPrinter::VisitFunctionDecl(Func<br>
>>          }<br>
>>          Out << ")";<br>
>>        }<br>
>> -      if (!Proto.empty())<br>
>> -        Out << Proto;<br>
>> -    } else {<br>
>> +    } else if (!ConversionDecl) {<br>
>>        if (FT && FT->hasTrailingReturn()) {<br>
>>          Out << "auto " << Proto << " -> ";<br>
>>          Proto.clear();<br>
>>        }<br>
>>        AFT->getReturnType().print(Out, Policy, Proto);<br>
>> +      Proto.clear();<br>
>>      }<br>
>> +    Out << Proto;<br>
>>    } else {<br>
>>      Ty.print(Out, Policy, Proto);<br>
>>    }<br>
>><br>
>> Modified: cfe/trunk/lib/AST/DeclarationName.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclarationName.cpp?rev=202167&r1=202166&r2=202167&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclarationName.cpp?rev=202167&r1=202166&r2=202167&view=diff</a><br>

>><br>
>> ==============================================================================<br>
>> --- cfe/trunk/lib/AST/DeclarationName.cpp (original)<br>
>> +++ cfe/trunk/lib/AST/DeclarationName.cpp Tue Feb 25 11:26:26 2014<br>
>> @@ -191,6 +191,7 @@ raw_ostream &operator<<(raw_ostream &OS,<br>
>>        return OS << *Rec->getDecl();<br>
>>      LangOptions LO;<br>
>>      LO.CPlusPlus = true;<br>
>> +    LO.Bool = true;<br>
>>      return OS << Type.getAsString(PrintingPolicy(LO));<br>
>>    }<br>
>>    case DeclarationName::CXXUsingDirective:<br>
>> @@ -546,6 +547,7 @@ void DeclarationNameInfo::printName(raw_<br>
>>          OS << "operator ";<br>
>>        LangOptions LO;<br>
>>        LO.CPlusPlus = true;<br>
>> +      LO.Bool = true;<br>
>>        OS << TInfo->getType().getAsString(PrintingPolicy(LO));<br>
>>      } else<br>
>>        OS << Name;<br>
>><br>
>> Modified: cfe/trunk/lib/AST/StmtPrinter.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=202167&r1=202166&r2=202167&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=202167&r1=202166&r2=202167&view=diff</a><br>

>><br>
>> ==============================================================================<br>
>> --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)<br>
>> +++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Feb 25 11:26:26 2014<br>
>> @@ -1296,6 +1296,12 @@ void StmtPrinter::VisitCXXOperatorCallEx<br>
>>  }<br>
>><br>
>>  void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) {<br>
>> +  // If we have a conversion operator call only print the argument.<br>
>> +  CXXMethodDecl *MD = Node->getMethodDecl();<br>
>> +  if (MD && isa<CXXConversionDecl>(MD)) {<br>
>> +    PrintExpr(Node->getImplicitObjectArgument());<br>
>> +    return;<br>
>> +  }<br>
><br>
><br>
> You should only do this if we have an implicit call to a conversion<br>
> operator. Given:<br>
><br>
>   auto x = (a & b).operator void*();<br>
><br>
> ... we should print out the call to 'operator void*'. I think the way to<br>
> detect this in the current AST is to look for a CastExpr whose cast kind is<br>
> CK_UserDefinedConversion, and to skip the CXXMemberCallExpr or<br>
> CXXConstructExpr inside it -- but maybe we should change the AST<br>
> representation here to more directly distinguish between an implicit<br>
> conversion operator call and an explicit one?<br>
<br>
</div></div>Using the CastExpr won't work for my use case. I have a<br>
CXXMemberCallExpr and I want to print it. The result used to be:<br>
<br>
Input: a & b<br>
Output: a & b.operator void*()<br>
<br>
so the StmtPrinter has changed semantics. The options I had was either<br>
add parens unconditionally. Then we lose idempotence as all parens<br>
already there will also be added, leading to gradual LISPification. Or<br>
just drop the explicit call.<br></blockquote><div><br></div><div>You could instead add a VisitImplicitCastExpr, and if it's a CK_UserDefinedConversion whose source is a CXXMemberCallExpr, strip out that call. But I much prefer representing this more directly in the AST.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I think a flag on the expression to see whether the call was written<br>
out explicitly would work, but I'm not sure how to implement it<br>
properly.<br></blockquote><div><br></div><div>I would like to see a separate class derived from CallExpr for an implicit call to a conversion operator, just as we do for overloaded operators. The documentation comment for CXXMemberCallExpr is pretty clear that it's not appropriate for this case =)</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
- Ben<br>
<div class="HOEnZb"><div class="h5"><br>
><br>
>><br>
>>    VisitCallExpr(cast<CallExpr>(Node));<br>
>>  }<br>
>><br>
>><br>
>> Modified: cfe/trunk/test/SemaCXX/ast-print.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ast-print.cpp?rev=202167&r1=202166&r2=202167&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ast-print.cpp?rev=202167&r1=202166&r2=202167&view=diff</a><br>

>><br>
>> ==============================================================================<br>
>> --- cfe/trunk/test/SemaCXX/ast-print.cpp (original)<br>
>> +++ cfe/trunk/test/SemaCXX/ast-print.cpp Tue Feb 25 11:26:26 2014<br>
>> @@ -1,4 +1,4 @@<br>
>> -// RUN: %clang_cc1 -ast-print %s | FileCheck %s<br>
>> +// RUN: %clang_cc1 -ast-print %s -std=gnu++11 | FileCheck %s<br>
>><br>
>>  // CHECK: r;<br>
>>  // CHECK-NEXT: (r->method());<br>
>> @@ -173,3 +173,26 @@ void test14() {<br>
>>  float test15() {<br>
>>    return __builtin_asinf(1.0F);<br>
>>  }<br>
>> +<br>
>> +namespace PR18776 {<br>
>> +struct A {<br>
>> +  operator void *();<br>
>> +  explicit operator bool();<br>
>> +  A operator&(A);<br>
>> +};<br>
>> +<br>
>> +// CHECK: struct A<br>
>> +// CHECK-NEXT: {{^[ ]*operator}} void *();<br>
>> +// CHECK-NEXT: {{^[ ]*explicit}} operator bool();<br>
>> +<br>
>> +void bar(void *);<br>
>> +<br>
>> +void foo() {<br>
>> +  A a, b;<br>
>> +  bar(a & b);<br>
>> +// CHECK: bar(a & b);<br>
>> +  if (a & b)<br>
>> +// CHECK: if (a & b)<br>
>> +    return;<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>
><br>
><br>
</div></div></blockquote></div><br></div></div>