r202167 - Pretty Printer: Fix printing of conversion operator decls and calls.
Richard Smith
richard at metafoo.co.uk
Tue Feb 25 13:43:38 PST 2014
On Tue, Feb 25, 2014 at 1:20 PM, Benjamin Kramer <benny.kra at gmail.com>wrote:
> On Tue, Feb 25, 2014 at 8:58 PM, Richard Smith <richard at metafoo.co.uk>
> wrote:
> > On Tue, Feb 25, 2014 at 9:26 AM, Benjamin Kramer <
> benny.kra at googlemail.com>
> > wrote:
> >>
> >> Author: d0k
> >> Date: Tue Feb 25 11:26:26 2014
> >> New Revision: 202167
> >>
> >> URL: http://llvm.org/viewvc/llvm-project?rev=202167&view=rev
> >> Log:
> >> Pretty Printer: Fix printing of conversion operator decls and calls.
> >>
> >> - Don't emit anything when we encounter a call to a conversion operator.
> >> "bar(a & b)" instead of "bar(a & b.operator int())"
> >> This preserves the semantics and is still idempotent if we print the
> AST
> >> multiple times.
> >>
> >> - Properly print declarations of conversion operators.
> >> "explicit operator bool();" instead of "bool operator _Bool();"
> >>
> >> PR18776.
> >>
> >> Modified:
> >> cfe/trunk/lib/AST/DeclPrinter.cpp
> >> cfe/trunk/lib/AST/DeclarationName.cpp
> >> cfe/trunk/lib/AST/StmtPrinter.cpp
> >> cfe/trunk/test/SemaCXX/ast-print.cpp
> >>
> >> Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
> >> URL:
> >>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=202167&r1=202166&r2=202167&view=diff
> >>
> >>
> ==============================================================================
> >> --- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
> >> +++ cfe/trunk/lib/AST/DeclPrinter.cpp Tue Feb 25 11:26:26 2014
> >> @@ -385,6 +385,7 @@ void DeclPrinter::VisitEnumConstantDecl(
> >>
> >> void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
> >> CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
> >> + CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
> >> if (!Policy.SuppressSpecifiers) {
> >> switch (D->getStorageClass()) {
> >> case SC_None: break;
> >> @@ -398,7 +399,8 @@ void DeclPrinter::VisitFunctionDecl(Func
> >> if (D->isInlineSpecified()) Out << "inline ";
> >> if (D->isVirtualAsWritten()) Out << "virtual ";
> >> if (D->isModulePrivate()) Out << "__module_private__ ";
> >> - if (CDecl && CDecl->isExplicitSpecified())
> >> + if ((CDecl && CDecl->isExplicitSpecified()) ||
> >> + (ConversionDecl && ConversionDecl->isExplicit()))
> >> Out << "explicit ";
> >> }
> >>
> >> @@ -536,15 +538,15 @@ void DeclPrinter::VisitFunctionDecl(Func
> >> }
> >> Out << ")";
> >> }
> >> - if (!Proto.empty())
> >> - Out << Proto;
> >> - } else {
> >> + } else if (!ConversionDecl) {
> >> if (FT && FT->hasTrailingReturn()) {
> >> Out << "auto " << Proto << " -> ";
> >> Proto.clear();
> >> }
> >> AFT->getReturnType().print(Out, Policy, Proto);
> >> + Proto.clear();
> >> }
> >> + Out << Proto;
> >> } else {
> >> Ty.print(Out, Policy, Proto);
> >> }
> >>
> >> Modified: cfe/trunk/lib/AST/DeclarationName.cpp
> >> URL:
> >>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclarationName.cpp?rev=202167&r1=202166&r2=202167&view=diff
> >>
> >>
> ==============================================================================
> >> --- cfe/trunk/lib/AST/DeclarationName.cpp (original)
> >> +++ cfe/trunk/lib/AST/DeclarationName.cpp Tue Feb 25 11:26:26 2014
> >> @@ -191,6 +191,7 @@ raw_ostream &operator<<(raw_ostream &OS,
> >> return OS << *Rec->getDecl();
> >> LangOptions LO;
> >> LO.CPlusPlus = true;
> >> + LO.Bool = true;
> >> return OS << Type.getAsString(PrintingPolicy(LO));
> >> }
> >> case DeclarationName::CXXUsingDirective:
> >> @@ -546,6 +547,7 @@ void DeclarationNameInfo::printName(raw_
> >> OS << "operator ";
> >> LangOptions LO;
> >> LO.CPlusPlus = true;
> >> + LO.Bool = true;
> >> OS << TInfo->getType().getAsString(PrintingPolicy(LO));
> >> } else
> >> OS << Name;
> >>
> >> Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
> >> URL:
> >>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=202167&r1=202166&r2=202167&view=diff
> >>
> >>
> ==============================================================================
> >> --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
> >> +++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Feb 25 11:26:26 2014
> >> @@ -1296,6 +1296,12 @@ void StmtPrinter::VisitCXXOperatorCallEx
> >> }
> >>
> >> void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) {
> >> + // If we have a conversion operator call only print the argument.
> >> + CXXMethodDecl *MD = Node->getMethodDecl();
> >> + if (MD && isa<CXXConversionDecl>(MD)) {
> >> + PrintExpr(Node->getImplicitObjectArgument());
> >> + return;
> >> + }
> >
> >
> > You should only do this if we have an implicit call to a conversion
> > operator. Given:
> >
> > auto x = (a & b).operator void*();
> >
> > ... we should print out the call to 'operator void*'. I think the way to
> > detect this in the current AST is to look for a CastExpr whose cast kind
> is
> > CK_UserDefinedConversion, and to skip the CXXMemberCallExpr or
> > CXXConstructExpr inside it -- but maybe we should change the AST
> > representation here to more directly distinguish between an implicit
> > conversion operator call and an explicit one?
>
> Using the CastExpr won't work for my use case. I have a
> CXXMemberCallExpr and I want to print it. The result used to be:
>
> Input: a & b
> Output: a & b.operator void*()
>
> so the StmtPrinter has changed semantics. The options I had was either
> add parens unconditionally. Then we lose idempotence as all parens
> already there will also be added, leading to gradual LISPification. Or
> just drop the explicit call.
>
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.
> I think a flag on the expression to see whether the call was written
> out explicitly would work, but I'm not sure how to implement it
> properly.
>
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 =)
> - Ben
>
> >
> >>
> >> VisitCallExpr(cast<CallExpr>(Node));
> >> }
> >>
> >>
> >> Modified: cfe/trunk/test/SemaCXX/ast-print.cpp
> >> URL:
> >>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ast-print.cpp?rev=202167&r1=202166&r2=202167&view=diff
> >>
> >>
> ==============================================================================
> >> --- cfe/trunk/test/SemaCXX/ast-print.cpp (original)
> >> +++ cfe/trunk/test/SemaCXX/ast-print.cpp Tue Feb 25 11:26:26 2014
> >> @@ -1,4 +1,4 @@
> >> -// RUN: %clang_cc1 -ast-print %s | FileCheck %s
> >> +// RUN: %clang_cc1 -ast-print %s -std=gnu++11 | FileCheck %s
> >>
> >> // CHECK: r;
> >> // CHECK-NEXT: (r->method());
> >> @@ -173,3 +173,26 @@ void test14() {
> >> float test15() {
> >> return __builtin_asinf(1.0F);
> >> }
> >> +
> >> +namespace PR18776 {
> >> +struct A {
> >> + operator void *();
> >> + explicit operator bool();
> >> + A operator&(A);
> >> +};
> >> +
> >> +// CHECK: struct A
> >> +// CHECK-NEXT: {{^[ ]*operator}} void *();
> >> +// CHECK-NEXT: {{^[ ]*explicit}} operator bool();
> >> +
> >> +void bar(void *);
> >> +
> >> +void foo() {
> >> + A a, b;
> >> + bar(a & b);
> >> +// CHECK: bar(a & b);
> >> + if (a & b)
> >> +// CHECK: if (a & b)
> >> + return;
> >> +}
> >> +};
> >>
> >>
> >> _______________________________________________
> >> cfe-commits mailing list
> >> cfe-commits at cs.uiuc.edu
> >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> >
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140225/8f225603/attachment.html>
More information about the cfe-commits
mailing list