2018-04-11 06:54:42 +08:00
|
|
|
//===- StmtPrinter.cpp - Printing implementation for Stmt ASTs ------------===//
|
2006-11-04 15:16:25 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2006-11-04 15:16:25 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2007-08-09 06:51:59 +08:00
|
|
|
// This file implements the Stmt::dumpPretty/Stmt::printPretty methods, which
|
|
|
|
// pretty print the AST back out to C code.
|
2006-11-04 15:16:25 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-07-05 04:19:54 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/Attr.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/AST/DeclBase.h"
|
2009-01-06 13:10:23 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2007-10-18 02:36:42 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2016-02-08 17:29:13 +08:00
|
|
|
#include "clang/AST/DeclOpenMP.h"
|
2011-01-15 09:15:58 +08:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
Completely reimplement __builtin_offsetof, based on a patch by Roberto
Amadini.
This change introduces a new expression node type, OffsetOfExpr, that
describes __builtin_offsetof. Previously, __builtin_offsetof was
implemented using a unary operator whose subexpression involved
various synthesized array-subscript and member-reference expressions,
which was ugly and made it very hard to instantiate as a
template. OffsetOfExpr represents the AST more faithfully, with proper
type source information and a more compact representation.
OffsetOfExpr also has support for dependent __builtin_offsetof
expressions; it can be value-dependent, but will never be
type-dependent (like sizeof or alignof). This commit introduces
template instantiation for __builtin_offsetof as well.
There are two major caveats to this patch:
1) CodeGen cannot handle the case where __builtin_offsetof is not a
constant expression, so it produces an error. So, to avoid
regressing in C, we retain the old UnaryOperator-based
__builtin_offsetof implementation in C while using the shiny new
OffsetOfExpr implementation in C++. The old implementation can go
away once we have proper CodeGen support for this case, which we
expect won't cause much trouble in C++.
2) __builtin_offsetof doesn't work well with non-POD class types,
particularly when the designated field is found within a base
class. I will address this in a subsequent patch.
Fixes PR5880 and a bunch of assertions when building Boost.Python
tests.
llvm-svn: 102542
2010-04-29 06:16:22 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2010-09-08 08:15:04 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#include "clang/AST/ExprObjC.h"
|
2015-08-25 22:24:04 +08:00
|
|
|
#include "clang/AST/ExprOpenMP.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#include "clang/AST/NestedNameSpecifier.h"
|
|
|
|
#include "clang/AST/OpenMPClause.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/PrettyPrinter.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#include "clang/AST/Stmt.h"
|
|
|
|
#include "clang/AST/StmtCXX.h"
|
|
|
|
#include "clang/AST/StmtObjC.h"
|
|
|
|
#include "clang/AST/StmtOpenMP.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/StmtVisitor.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#include "clang/AST/TemplateBase.h"
|
|
|
|
#include "clang/AST/Type.h"
|
2013-02-09 06:30:27 +08:00
|
|
|
#include "clang/Basic/CharInfo.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#include "clang/Basic/ExpressionTraits.h"
|
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
|
|
|
#include "clang/Basic/LLVM.h"
|
|
|
|
#include "clang/Basic/Lambda.h"
|
|
|
|
#include "clang/Basic/OpenMPKinds.h"
|
|
|
|
#include "clang/Basic/OperatorKinds.h"
|
|
|
|
#include "clang/Basic/SourceLocation.h"
|
|
|
|
#include "clang/Basic/TypeTraits.h"
|
2017-08-17 21:41:55 +08:00
|
|
|
#include "clang/Lex/Lexer.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
2012-02-04 21:45:25 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2013-02-09 06:30:27 +08:00
|
|
|
#include "llvm/Support/Format.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <cassert>
|
|
|
|
#include <string>
|
|
|
|
|
2006-11-04 15:16:25 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// StmtPrinter Visitor
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
namespace {
|
|
|
|
|
2009-11-29 03:03:38 +08:00
|
|
|
class StmtPrinter : public StmtVisitor<StmtPrinter> {
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream &OS;
|
2006-11-04 15:16:25 +08:00
|
|
|
unsigned IndentLevel;
|
2018-04-11 06:54:42 +08:00
|
|
|
PrinterHelper* Helper;
|
2009-05-30 04:38:28 +08:00
|
|
|
PrintingPolicy Policy;
|
2018-09-15 10:02:31 +08:00
|
|
|
std::string NL;
|
2017-08-17 21:41:55 +08:00
|
|
|
const ASTContext *Context;
|
2009-05-30 04:38:28 +08:00
|
|
|
|
2006-11-04 15:16:25 +08:00
|
|
|
public:
|
2017-08-17 21:41:55 +08:00
|
|
|
StmtPrinter(raw_ostream &os, PrinterHelper *helper,
|
|
|
|
const PrintingPolicy &Policy, unsigned Indentation = 0,
|
2018-09-15 10:02:31 +08:00
|
|
|
StringRef NL = "\n",
|
2017-08-17 21:41:55 +08:00
|
|
|
const ASTContext *Context = nullptr)
|
|
|
|
: OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy),
|
2018-09-15 10:02:31 +08:00
|
|
|
NL(NL), Context(Context) {}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 04:38:28 +08:00
|
|
|
void PrintStmt(Stmt *S) {
|
|
|
|
PrintStmt(S, Policy.Indentation);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrintStmt(Stmt *S, int SubIndent) {
|
2007-05-21 06:52:15 +08:00
|
|
|
IndentLevel += SubIndent;
|
2007-06-01 02:21:33 +08:00
|
|
|
if (S && isa<Expr>(S)) {
|
2006-11-05 02:52:07 +08:00
|
|
|
// If this is an expr used in a stmt context, indent and newline it.
|
|
|
|
Indent();
|
2007-08-21 12:04:25 +08:00
|
|
|
Visit(S);
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << ";" << NL;
|
2006-11-05 02:52:07 +08:00
|
|
|
} else if (S) {
|
2007-08-21 12:04:25 +08:00
|
|
|
Visit(S);
|
2006-11-05 02:52:07 +08:00
|
|
|
} else {
|
2018-09-15 10:02:31 +08:00
|
|
|
Indent() << "<<<NULL STATEMENT>>>" << NL;
|
2006-11-05 02:52:07 +08:00
|
|
|
}
|
2007-05-21 06:52:15 +08:00
|
|
|
IndentLevel -= SubIndent;
|
2006-11-05 02:52:07 +08:00
|
|
|
}
|
2009-05-30 08:19:54 +08:00
|
|
|
|
2018-09-29 02:44:09 +08:00
|
|
|
void PrintInitStmt(Stmt *S, unsigned PrefixWidth) {
|
|
|
|
// FIXME: Cope better with odd prefix widths.
|
|
|
|
IndentLevel += (PrefixWidth + 1) / 2;
|
|
|
|
if (auto *DS = dyn_cast<DeclStmt>(S))
|
|
|
|
PrintRawDeclStmt(DS);
|
|
|
|
else
|
|
|
|
PrintExpr(cast<Expr>(S));
|
|
|
|
OS << "; ";
|
|
|
|
IndentLevel -= (PrefixWidth + 1) / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrintControlledStmt(Stmt *S) {
|
|
|
|
if (auto *CS = dyn_cast<CompoundStmt>(S)) {
|
|
|
|
OS << " ";
|
|
|
|
PrintRawCompoundStmt(CS);
|
|
|
|
OS << NL;
|
|
|
|
} else {
|
|
|
|
OS << NL;
|
|
|
|
PrintStmt(S);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-21 07:04:55 +08:00
|
|
|
void PrintRawCompoundStmt(CompoundStmt *S);
|
2007-06-06 04:52:47 +08:00
|
|
|
void PrintRawDecl(Decl *D);
|
2012-10-17 07:45:15 +08:00
|
|
|
void PrintRawDeclStmt(const DeclStmt *S);
|
Pretty print if/else/elseif chains nicer, like this:
void printutf8(unsigned int X) {
if (X <= 127)
printf("%c", (char)X);
else if (X <= 2047)
printf("%d %d ", 128 + 64 + (X >> 6), 128 + (X & ((1 << 6) - 1)));
else if (X <= 65535)
printf("%c%c%c", 128 + 64 + 32 + (X >> 12), 128 + ((X >> 6) & 63), 128 + (X & 63));
else
printf("UNKNOWN %d\n", X);
instead of:
if (X <= 127)
printf("%c", (char)X);
else
if (X <= 2047)
printf("%d %d ", 128 + 64 + (X >> 6), 128 + (X & ((1 << 6) - 1)));
else
if (X <= 65535)
printf("%c%c%c", 128 + 64 + 32 + (X >> 12), 128 + ((X >> 6) & 63), 128 + (X & 63));
else
printf("UNKNOWN %d\n", X);
llvm-svn: 39648
2007-06-12 06:26:23 +08:00
|
|
|
void PrintRawIfStmt(IfStmt *If);
|
2008-12-23 05:35:02 +08:00
|
|
|
void PrintRawCXXCatchStmt(CXXCatchStmt *Catch);
|
2011-02-09 05:17:54 +08:00
|
|
|
void PrintCallArgs(CallExpr *E);
|
2011-04-28 09:08:34 +08:00
|
|
|
void PrintRawSEHExceptHandler(SEHExceptStmt *S);
|
|
|
|
void PrintRawSEHFinallyStmt(SEHFinallyStmt *S);
|
2017-11-22 01:08:48 +08:00
|
|
|
void PrintOMPExecutableDirective(OMPExecutableDirective *S,
|
|
|
|
bool ForceNoStmt = false);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-11-05 02:52:07 +08:00
|
|
|
void PrintExpr(Expr *E) {
|
|
|
|
if (E)
|
2007-08-21 12:04:25 +08:00
|
|
|
Visit(E);
|
2006-11-04 15:16:25 +08:00
|
|
|
else
|
2006-11-05 02:52:07 +08:00
|
|
|
OS << "<null expr>";
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream &Indent(int Delta = 0) {
|
2009-05-30 04:38:28 +08:00
|
|
|
for (int i = 0, e = IndentLevel+Delta; i < e; ++i)
|
|
|
|
OS << " ";
|
2006-11-04 15:16:25 +08:00
|
|
|
return OS;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
void Visit(Stmt* S) {
|
2007-09-01 05:30:12 +08:00
|
|
|
if (Helper && Helper->handledStmt(S,OS))
|
|
|
|
return;
|
|
|
|
else StmtVisitor<StmtPrinter>::Visit(S);
|
|
|
|
}
|
2014-02-27 16:29:12 +08:00
|
|
|
|
2010-10-23 16:21:37 +08:00
|
|
|
void VisitStmt(Stmt *Node) LLVM_ATTRIBUTE_UNUSED {
|
2018-09-15 10:02:31 +08:00
|
|
|
Indent() << "<<unknown stmt type>>" << NL;
|
2010-08-15 09:15:33 +08:00
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2010-10-23 16:21:37 +08:00
|
|
|
void VisitExpr(Expr *Node) LLVM_ATTRIBUTE_UNUSED {
|
2010-08-15 09:15:33 +08:00
|
|
|
OS << "<<unknown expr type>>";
|
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2010-08-15 09:15:33 +08:00
|
|
|
void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-08-15 09:15:33 +08:00
|
|
|
#define ABSTRACT_STMT(CLASS)
|
2008-11-14 20:46:07 +08:00
|
|
|
#define STMT(CLASS, PARENT) \
|
2007-08-21 12:04:25 +08:00
|
|
|
void Visit##CLASS(CLASS *Node);
|
2010-05-05 23:24:00 +08:00
|
|
|
#include "clang/AST/StmtNodes.inc"
|
2006-11-05 04:18:38 +08:00
|
|
|
};
|
2018-04-11 06:54:42 +08:00
|
|
|
|
|
|
|
} // namespace
|
2006-11-05 02:52:07 +08:00
|
|
|
|
2006-11-05 04:18:38 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Stmt printing methods.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-05-21 07:04:55 +08:00
|
|
|
/// PrintRawCompoundStmt - Print a compound stmt without indenting the {, and
|
|
|
|
/// with no newline after the }.
|
|
|
|
void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) {
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << "{" << NL;
|
2014-03-17 22:19:37 +08:00
|
|
|
for (auto *I : Node->body())
|
|
|
|
PrintStmt(I);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-05-21 07:04:55 +08:00
|
|
|
Indent() << "}";
|
|
|
|
}
|
|
|
|
|
2007-06-06 04:52:47 +08:00
|
|
|
void StmtPrinter::PrintRawDecl(Decl *D) {
|
2009-06-30 10:35:04 +08:00
|
|
|
D->print(OS, Policy, IndentLevel);
|
2009-02-11 04:16:46 +08:00
|
|
|
}
|
|
|
|
|
2012-10-17 07:45:15 +08:00
|
|
|
void StmtPrinter::PrintRawDeclStmt(const DeclStmt *S) {
|
2018-04-11 06:54:42 +08:00
|
|
|
SmallVector<Decl *, 2> Decls(S->decls());
|
2009-06-30 10:35:04 +08:00
|
|
|
Decl::printGroup(Decls.data(), Decls.size(), OS, Policy, IndentLevel);
|
2008-10-07 02:39:36 +08:00
|
|
|
}
|
2007-06-06 04:52:47 +08:00
|
|
|
|
|
|
|
void StmtPrinter::VisitNullStmt(NullStmt *Node) {
|
2018-09-15 10:02:31 +08:00
|
|
|
Indent() << ";" << NL;
|
2007-06-06 04:52:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitDeclStmt(DeclStmt *Node) {
|
2009-05-30 08:19:54 +08:00
|
|
|
Indent();
|
|
|
|
PrintRawDeclStmt(Node);
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << ";" << NL;
|
2007-05-30 06:59:26 +08:00
|
|
|
}
|
|
|
|
|
2007-05-21 07:04:55 +08:00
|
|
|
void StmtPrinter::VisitCompoundStmt(CompoundStmt *Node) {
|
|
|
|
Indent();
|
|
|
|
PrintRawCompoundStmt(Node);
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << "" << NL;
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
|
|
|
|
2006-11-05 08:19:50 +08:00
|
|
|
void StmtPrinter::VisitCaseStmt(CaseStmt *Node) {
|
2007-05-21 06:52:15 +08:00
|
|
|
Indent(-1) << "case ";
|
2006-11-05 08:19:50 +08:00
|
|
|
PrintExpr(Node->getLHS());
|
|
|
|
if (Node->getRHS()) {
|
|
|
|
OS << " ... ";
|
|
|
|
PrintExpr(Node->getRHS());
|
|
|
|
}
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << ":" << NL;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-05-21 06:52:15 +08:00
|
|
|
PrintStmt(Node->getSubStmt(), 0);
|
2006-11-05 08:19:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitDefaultStmt(DefaultStmt *Node) {
|
2018-09-15 10:02:31 +08:00
|
|
|
Indent(-1) << "default:" << NL;
|
2007-05-21 06:52:15 +08:00
|
|
|
PrintStmt(Node->getSubStmt(), 0);
|
2006-11-05 08:19:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
|
2018-09-15 10:02:31 +08:00
|
|
|
Indent(-1) << Node->getName() << ":" << NL;
|
2007-05-21 06:52:15 +08:00
|
|
|
PrintStmt(Node->getSubStmt(), 0);
|
2006-11-05 08:19:50 +08:00
|
|
|
}
|
|
|
|
|
2012-04-14 08:33:13 +08:00
|
|
|
void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
|
2014-06-06 20:40:24 +08:00
|
|
|
for (const auto *Attr : Node->getAttrs()) {
|
2014-06-14 01:57:25 +08:00
|
|
|
Attr->printPretty(OS, Policy);
|
2014-06-06 20:40:24 +08:00
|
|
|
}
|
|
|
|
|
2012-04-14 08:33:13 +08:00
|
|
|
PrintStmt(Node->getSubStmt(), 0);
|
|
|
|
}
|
|
|
|
|
Pretty print if/else/elseif chains nicer, like this:
void printutf8(unsigned int X) {
if (X <= 127)
printf("%c", (char)X);
else if (X <= 2047)
printf("%d %d ", 128 + 64 + (X >> 6), 128 + (X & ((1 << 6) - 1)));
else if (X <= 65535)
printf("%c%c%c", 128 + 64 + 32 + (X >> 12), 128 + ((X >> 6) & 63), 128 + (X & 63));
else
printf("UNKNOWN %d\n", X);
instead of:
if (X <= 127)
printf("%c", (char)X);
else
if (X <= 2047)
printf("%d %d ", 128 + 64 + (X >> 6), 128 + (X & ((1 << 6) - 1)));
else
if (X <= 65535)
printf("%c%c%c", 128 + 64 + 32 + (X >> 12), 128 + ((X >> 6) & 63), 128 + (X & 63));
else
printf("UNKNOWN %d\n", X);
llvm-svn: 39648
2007-06-12 06:26:23 +08:00
|
|
|
void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
|
2009-02-08 04:05:48 +08:00
|
|
|
OS << "if (";
|
2018-09-29 02:44:09 +08:00
|
|
|
if (If->getInit())
|
|
|
|
PrintInitStmt(If->getInit(), 4);
|
2012-10-17 07:45:15 +08:00
|
|
|
if (const DeclStmt *DS = If->getConditionVariableDeclStmt())
|
|
|
|
PrintRawDeclStmt(DS);
|
|
|
|
else
|
|
|
|
PrintExpr(If->getCond());
|
2009-02-08 04:05:48 +08:00
|
|
|
OS << ')';
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
if (auto *CS = dyn_cast<CompoundStmt>(If->getThen())) {
|
2007-05-21 07:04:55 +08:00
|
|
|
OS << ' ';
|
|
|
|
PrintRawCompoundStmt(CS);
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << (If->getElse() ? " " : NL);
|
2007-05-21 07:04:55 +08:00
|
|
|
} else {
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2007-05-21 07:04:55 +08:00
|
|
|
PrintStmt(If->getThen());
|
|
|
|
if (If->getElse()) Indent();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-05-21 07:04:55 +08:00
|
|
|
if (Stmt *Else = If->getElse()) {
|
|
|
|
OS << "else";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
|
2007-05-21 07:04:55 +08:00
|
|
|
OS << ' ';
|
|
|
|
PrintRawCompoundStmt(CS);
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2018-04-11 06:54:42 +08:00
|
|
|
} else if (auto *ElseIf = dyn_cast<IfStmt>(Else)) {
|
Pretty print if/else/elseif chains nicer, like this:
void printutf8(unsigned int X) {
if (X <= 127)
printf("%c", (char)X);
else if (X <= 2047)
printf("%d %d ", 128 + 64 + (X >> 6), 128 + (X & ((1 << 6) - 1)));
else if (X <= 65535)
printf("%c%c%c", 128 + 64 + 32 + (X >> 12), 128 + ((X >> 6) & 63), 128 + (X & 63));
else
printf("UNKNOWN %d\n", X);
instead of:
if (X <= 127)
printf("%c", (char)X);
else
if (X <= 2047)
printf("%d %d ", 128 + 64 + (X >> 6), 128 + (X & ((1 << 6) - 1)));
else
if (X <= 65535)
printf("%c%c%c", 128 + 64 + 32 + (X >> 12), 128 + ((X >> 6) & 63), 128 + (X & 63));
else
printf("UNKNOWN %d\n", X);
llvm-svn: 39648
2007-06-12 06:26:23 +08:00
|
|
|
OS << ' ';
|
|
|
|
PrintRawIfStmt(ElseIf);
|
2007-05-21 07:04:55 +08:00
|
|
|
} else {
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2007-05-21 07:04:55 +08:00
|
|
|
PrintStmt(If->getElse());
|
|
|
|
}
|
2006-11-05 02:52:07 +08:00
|
|
|
}
|
2006-11-05 04:40:44 +08:00
|
|
|
}
|
|
|
|
|
Pretty print if/else/elseif chains nicer, like this:
void printutf8(unsigned int X) {
if (X <= 127)
printf("%c", (char)X);
else if (X <= 2047)
printf("%d %d ", 128 + 64 + (X >> 6), 128 + (X & ((1 << 6) - 1)));
else if (X <= 65535)
printf("%c%c%c", 128 + 64 + 32 + (X >> 12), 128 + ((X >> 6) & 63), 128 + (X & 63));
else
printf("UNKNOWN %d\n", X);
instead of:
if (X <= 127)
printf("%c", (char)X);
else
if (X <= 2047)
printf("%d %d ", 128 + 64 + (X >> 6), 128 + (X & ((1 << 6) - 1)));
else
if (X <= 65535)
printf("%c%c%c", 128 + 64 + 32 + (X >> 12), 128 + ((X >> 6) & 63), 128 + (X & 63));
else
printf("UNKNOWN %d\n", X);
llvm-svn: 39648
2007-06-12 06:26:23 +08:00
|
|
|
void StmtPrinter::VisitIfStmt(IfStmt *If) {
|
|
|
|
Indent();
|
|
|
|
PrintRawIfStmt(If);
|
|
|
|
}
|
|
|
|
|
2006-11-05 04:59:27 +08:00
|
|
|
void StmtPrinter::VisitSwitchStmt(SwitchStmt *Node) {
|
|
|
|
Indent() << "switch (";
|
2018-09-29 02:44:09 +08:00
|
|
|
if (Node->getInit())
|
|
|
|
PrintInitStmt(Node->getInit(), 8);
|
2012-10-17 07:45:15 +08:00
|
|
|
if (const DeclStmt *DS = Node->getConditionVariableDeclStmt())
|
|
|
|
PrintRawDeclStmt(DS);
|
|
|
|
else
|
|
|
|
PrintExpr(Node->getCond());
|
2007-05-21 07:04:55 +08:00
|
|
|
OS << ")";
|
2018-09-29 02:44:09 +08:00
|
|
|
PrintControlledStmt(Node->getBody());
|
2006-11-05 04:59:27 +08:00
|
|
|
}
|
|
|
|
|
2006-11-05 04:40:44 +08:00
|
|
|
void StmtPrinter::VisitWhileStmt(WhileStmt *Node) {
|
|
|
|
Indent() << "while (";
|
2012-10-17 07:45:15 +08:00
|
|
|
if (const DeclStmt *DS = Node->getConditionVariableDeclStmt())
|
|
|
|
PrintRawDeclStmt(DS);
|
|
|
|
else
|
|
|
|
PrintExpr(Node->getCond());
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << ")" << NL;
|
2006-11-05 04:40:44 +08:00
|
|
|
PrintStmt(Node->getBody());
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitDoStmt(DoStmt *Node) {
|
2007-09-16 05:49:37 +08:00
|
|
|
Indent() << "do ";
|
2018-04-11 06:54:42 +08:00
|
|
|
if (auto *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
|
2007-09-16 05:49:37 +08:00
|
|
|
PrintRawCompoundStmt(CS);
|
|
|
|
OS << " ";
|
|
|
|
} else {
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2007-09-16 05:49:37 +08:00
|
|
|
PrintStmt(Node->getBody());
|
|
|
|
Indent();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-17 09:05:34 +08:00
|
|
|
OS << "while (";
|
2006-11-05 04:40:44 +08:00
|
|
|
PrintExpr(Node->getCond());
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << ");" << NL;
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
|
|
|
|
2006-11-05 04:18:38 +08:00
|
|
|
void StmtPrinter::VisitForStmt(ForStmt *Node) {
|
|
|
|
Indent() << "for (";
|
2018-09-29 02:44:09 +08:00
|
|
|
if (Node->getInit())
|
|
|
|
PrintInitStmt(Node->getInit(), 5);
|
|
|
|
else
|
|
|
|
OS << (Node->getCond() ? "; " : ";");
|
|
|
|
if (Node->getCond())
|
2007-06-06 04:52:47 +08:00
|
|
|
PrintExpr(Node->getCond());
|
2007-09-16 05:49:37 +08:00
|
|
|
OS << ";";
|
|
|
|
if (Node->getInc()) {
|
|
|
|
OS << " ";
|
2007-06-06 04:52:47 +08:00
|
|
|
PrintExpr(Node->getInc());
|
2007-09-16 05:49:37 +08:00
|
|
|
}
|
2018-09-29 02:44:09 +08:00
|
|
|
OS << ")";
|
|
|
|
PrintControlledStmt(Node->getBody());
|
2006-11-05 04:18:38 +08:00
|
|
|
}
|
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) {
|
2008-01-03 06:54:34 +08:00
|
|
|
Indent() << "for (";
|
2018-04-11 06:54:42 +08:00
|
|
|
if (auto *DS = dyn_cast<DeclStmt>(Node->getElement()))
|
2008-10-07 02:39:36 +08:00
|
|
|
PrintRawDeclStmt(DS);
|
2008-01-03 06:54:34 +08:00
|
|
|
else
|
|
|
|
PrintExpr(cast<Expr>(Node->getElement()));
|
|
|
|
OS << " in ";
|
|
|
|
PrintExpr(Node->getCollection());
|
2018-09-29 02:44:09 +08:00
|
|
|
OS << ")";
|
|
|
|
PrintControlledStmt(Node->getBody());
|
2008-01-03 06:54:34 +08:00
|
|
|
}
|
|
|
|
|
2011-04-15 06:09:26 +08:00
|
|
|
void StmtPrinter::VisitCXXForRangeStmt(CXXForRangeStmt *Node) {
|
|
|
|
Indent() << "for (";
|
2018-09-29 02:44:09 +08:00
|
|
|
if (Node->getInit())
|
|
|
|
PrintInitStmt(Node->getInit(), 5);
|
2011-04-15 06:09:26 +08:00
|
|
|
PrintingPolicy SubPolicy(Policy);
|
|
|
|
SubPolicy.SuppressInitializers = true;
|
|
|
|
Node->getLoopVariable()->print(OS, SubPolicy, IndentLevel);
|
|
|
|
OS << " : ";
|
|
|
|
PrintExpr(Node->getRangeInit());
|
2018-09-29 02:44:09 +08:00
|
|
|
OS << ")";
|
|
|
|
PrintControlledStmt(Node->getBody());
|
2011-04-15 06:09:26 +08:00
|
|
|
}
|
|
|
|
|
2011-10-25 09:33:02 +08:00
|
|
|
void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) {
|
|
|
|
Indent();
|
|
|
|
if (Node->isIfExists())
|
|
|
|
OS << "__if_exists (";
|
|
|
|
else
|
|
|
|
OS << "__if_not_exists (";
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-10-25 09:33:02 +08:00
|
|
|
if (NestedNameSpecifier *Qualifier
|
|
|
|
= Node->getQualifierLoc().getNestedNameSpecifier())
|
|
|
|
Qualifier->print(OS, Policy);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-10-25 09:33:02 +08:00
|
|
|
OS << Node->getNameInfo() << ") ";
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-10-25 09:33:02 +08:00
|
|
|
PrintRawCompoundStmt(Node->getSubStmt());
|
|
|
|
}
|
|
|
|
|
2006-11-05 09:46:01 +08:00
|
|
|
void StmtPrinter::VisitGotoStmt(GotoStmt *Node) {
|
2013-12-12 07:44:02 +08:00
|
|
|
Indent() << "goto " << Node->getLabel()->getName() << ";";
|
2018-09-15 10:02:31 +08:00
|
|
|
if (Policy.IncludeNewlines) OS << NL;
|
2006-11-05 09:46:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitIndirectGotoStmt(IndirectGotoStmt *Node) {
|
2006-11-05 09:51:06 +08:00
|
|
|
Indent() << "goto *";
|
2006-11-05 09:46:01 +08:00
|
|
|
PrintExpr(Node->getTarget());
|
2013-12-12 07:44:02 +08:00
|
|
|
OS << ";";
|
2018-09-15 10:02:31 +08:00
|
|
|
if (Policy.IncludeNewlines) OS << NL;
|
2006-11-05 09:46:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitContinueStmt(ContinueStmt *Node) {
|
2013-12-12 07:44:02 +08:00
|
|
|
Indent() << "continue;";
|
2018-09-15 10:02:31 +08:00
|
|
|
if (Policy.IncludeNewlines) OS << NL;
|
2006-11-05 09:46:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitBreakStmt(BreakStmt *Node) {
|
2013-12-12 07:44:02 +08:00
|
|
|
Indent() << "break;";
|
2018-09-15 10:02:31 +08:00
|
|
|
if (Policy.IncludeNewlines) OS << NL;
|
2006-11-05 09:46:01 +08:00
|
|
|
}
|
|
|
|
|
2006-11-05 02:52:07 +08:00
|
|
|
void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) {
|
|
|
|
Indent() << "return";
|
|
|
|
if (Node->getRetValue()) {
|
|
|
|
OS << " ";
|
|
|
|
PrintExpr(Node->getRetValue());
|
|
|
|
}
|
2013-12-12 07:44:02 +08:00
|
|
|
OS << ";";
|
2018-09-15 10:02:31 +08:00
|
|
|
if (Policy.IncludeNewlines) OS << NL;
|
2006-11-05 02:52:07 +08:00
|
|
|
}
|
2006-11-04 15:16:25 +08:00
|
|
|
|
2012-08-25 08:11:56 +08:00
|
|
|
void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) {
|
2007-11-24 07:12:25 +08:00
|
|
|
Indent() << "asm ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-24 07:12:25 +08:00
|
|
|
if (Node->isVolatile())
|
|
|
|
OS << "volatile ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-24 07:12:25 +08:00
|
|
|
OS << "(";
|
2007-11-21 03:21:03 +08:00
|
|
|
VisitStringLiteral(Node->getAsmString());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-22 09:36:19 +08:00
|
|
|
// Outputs
|
|
|
|
if (Node->getNumOutputs() != 0 || Node->getNumInputs() != 0 ||
|
|
|
|
Node->getNumClobbers() != 0)
|
|
|
|
OS << " : ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-22 09:36:19 +08:00
|
|
|
for (unsigned i = 0, e = Node->getNumOutputs(); i != e; ++i) {
|
|
|
|
if (i != 0)
|
|
|
|
OS << ", ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-22 09:36:19 +08:00
|
|
|
if (!Node->getOutputName(i).empty()) {
|
|
|
|
OS << '[';
|
|
|
|
OS << Node->getOutputName(i);
|
|
|
|
OS << "] ";
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-10 12:59:06 +08:00
|
|
|
VisitStringLiteral(Node->getOutputConstraintLiteral(i));
|
2015-06-09 22:13:31 +08:00
|
|
|
OS << " (";
|
2007-11-22 09:36:19 +08:00
|
|
|
Visit(Node->getOutputExpr(i));
|
2015-06-09 22:13:31 +08:00
|
|
|
OS << ")";
|
2007-11-22 09:36:19 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-22 09:36:19 +08:00
|
|
|
// Inputs
|
|
|
|
if (Node->getNumInputs() != 0 || Node->getNumClobbers() != 0)
|
|
|
|
OS << " : ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-22 09:36:19 +08:00
|
|
|
for (unsigned i = 0, e = Node->getNumInputs(); i != e; ++i) {
|
|
|
|
if (i != 0)
|
|
|
|
OS << ", ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-22 09:36:19 +08:00
|
|
|
if (!Node->getInputName(i).empty()) {
|
|
|
|
OS << '[';
|
|
|
|
OS << Node->getInputName(i);
|
|
|
|
OS << "] ";
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-10 12:59:06 +08:00
|
|
|
VisitStringLiteral(Node->getInputConstraintLiteral(i));
|
2015-06-09 22:13:31 +08:00
|
|
|
OS << " (";
|
2007-11-22 09:36:19 +08:00
|
|
|
Visit(Node->getInputExpr(i));
|
2015-06-09 22:13:31 +08:00
|
|
|
OS << ")";
|
2007-11-22 09:36:19 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-22 09:36:19 +08:00
|
|
|
// Clobbers
|
|
|
|
if (Node->getNumClobbers() != 0)
|
|
|
|
OS << " : ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-22 09:36:19 +08:00
|
|
|
for (unsigned i = 0, e = Node->getNumClobbers(); i != e; ++i) {
|
|
|
|
if (i != 0)
|
|
|
|
OS << ", ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-08-28 07:28:41 +08:00
|
|
|
VisitStringLiteral(Node->getClobberStringLiteral(i));
|
2007-11-22 09:36:19 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2013-12-12 07:44:02 +08:00
|
|
|
OS << ");";
|
2018-09-15 10:02:31 +08:00
|
|
|
if (Policy.IncludeNewlines) OS << NL;
|
2007-10-29 12:04:16 +08:00
|
|
|
}
|
|
|
|
|
2012-06-12 04:47:18 +08:00
|
|
|
void StmtPrinter::VisitMSAsmStmt(MSAsmStmt *Node) {
|
|
|
|
// FIXME: Implement MS style inline asm statement printer.
|
2012-08-16 00:53:30 +08:00
|
|
|
Indent() << "__asm ";
|
|
|
|
if (Node->hasBraces())
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << "{" << NL;
|
|
|
|
OS << Node->getAsmString() << NL;
|
2012-08-16 00:53:30 +08:00
|
|
|
if (Node->hasBraces())
|
2018-09-15 10:02:31 +08:00
|
|
|
Indent() << "}" << NL;
|
2012-06-12 04:47:18 +08:00
|
|
|
}
|
|
|
|
|
2013-04-17 02:53:08 +08:00
|
|
|
void StmtPrinter::VisitCapturedStmt(CapturedStmt *Node) {
|
2013-04-17 03:37:38 +08:00
|
|
|
PrintStmt(Node->getCapturedDecl()->getBody());
|
2013-04-17 02:53:08 +08:00
|
|
|
}
|
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
|
2007-11-03 02:16:07 +08:00
|
|
|
Indent() << "@try";
|
2018-04-11 06:54:42 +08:00
|
|
|
if (auto *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) {
|
2007-11-03 02:16:07 +08:00
|
|
|
PrintRawCompoundStmt(TS);
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2007-11-03 02:16:07 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-04-24 06:50:49 +08:00
|
|
|
for (unsigned I = 0, N = Node->getNumCatchStmts(); I != N; ++I) {
|
|
|
|
ObjCAtCatchStmt *catchStmt = Node->getCatchStmt(I);
|
2007-11-03 02:16:07 +08:00
|
|
|
Indent() << "@catch(";
|
2009-03-04 03:52:17 +08:00
|
|
|
if (catchStmt->getCatchParamDecl()) {
|
|
|
|
if (Decl *DS = catchStmt->getCatchParamDecl())
|
|
|
|
PrintRawDecl(DS);
|
2007-11-03 02:16:07 +08:00
|
|
|
}
|
|
|
|
OS << ")";
|
2018-04-11 06:54:42 +08:00
|
|
|
if (auto *CS = dyn_cast<CompoundStmt>(catchStmt->getCatchBody())) {
|
2009-09-09 23:08:12 +08:00
|
|
|
PrintRawCompoundStmt(CS);
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2007-11-03 02:16:07 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
if (auto *FS = static_cast<ObjCAtFinallyStmt *>(Node->getFinallyStmt())) {
|
2007-11-07 08:46:42 +08:00
|
|
|
Indent() << "@finally";
|
|
|
|
PrintRawCompoundStmt(dyn_cast<CompoundStmt>(FS->getFinallyBody()));
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2007-11-02 05:12:44 +08:00
|
|
|
}
|
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
void StmtPrinter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Node) {
|
2007-11-02 05:12:44 +08:00
|
|
|
}
|
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
void StmtPrinter::VisitObjCAtCatchStmt (ObjCAtCatchStmt *Node) {
|
2018-09-15 10:02:31 +08:00
|
|
|
Indent() << "@catch (...) { /* todo */ } " << NL;
|
2007-11-02 05:12:44 +08:00
|
|
|
}
|
|
|
|
|
2008-01-31 01:38:29 +08:00
|
|
|
void StmtPrinter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *Node) {
|
2007-11-07 10:00:49 +08:00
|
|
|
Indent() << "@throw";
|
|
|
|
if (Node->getThrowExpr()) {
|
|
|
|
OS << " ";
|
|
|
|
PrintExpr(Node->getThrowExpr());
|
|
|
|
}
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << ";" << NL;
|
2007-11-07 10:00:49 +08:00
|
|
|
}
|
|
|
|
|
2016-07-16 08:35:23 +08:00
|
|
|
void StmtPrinter::VisitObjCAvailabilityCheckExpr(
|
|
|
|
ObjCAvailabilityCheckExpr *Node) {
|
|
|
|
OS << "@available(...)";
|
|
|
|
}
|
|
|
|
|
2008-01-31 01:38:29 +08:00
|
|
|
void StmtPrinter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Node) {
|
2008-01-30 02:21:32 +08:00
|
|
|
Indent() << "@synchronized (";
|
|
|
|
PrintExpr(Node->getSynchExpr());
|
|
|
|
OS << ")";
|
2008-01-31 01:38:29 +08:00
|
|
|
PrintRawCompoundStmt(Node->getSynchBody());
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2008-01-30 02:21:32 +08:00
|
|
|
}
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
void StmtPrinter::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *Node) {
|
|
|
|
Indent() << "@autoreleasepool";
|
|
|
|
PrintRawCompoundStmt(dyn_cast<CompoundStmt>(Node->getSubStmt()));
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
|
2008-12-23 05:35:02 +08:00
|
|
|
void StmtPrinter::PrintRawCXXCatchStmt(CXXCatchStmt *Node) {
|
|
|
|
OS << "catch (";
|
2008-12-23 03:15:10 +08:00
|
|
|
if (Decl *ExDecl = Node->getExceptionDecl())
|
|
|
|
PrintRawDecl(ExDecl);
|
|
|
|
else
|
|
|
|
OS << "...";
|
|
|
|
OS << ") ";
|
|
|
|
PrintRawCompoundStmt(cast<CompoundStmt>(Node->getHandlerBlock()));
|
2008-12-23 05:35:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCXXCatchStmt(CXXCatchStmt *Node) {
|
|
|
|
Indent();
|
|
|
|
PrintRawCXXCatchStmt(Node);
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2008-12-23 05:35:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) {
|
|
|
|
Indent() << "try ";
|
|
|
|
PrintRawCompoundStmt(Node->getTryBlock());
|
2009-09-09 23:08:12 +08:00
|
|
|
for (unsigned i = 0, e = Node->getNumHandlers(); i < e; ++i) {
|
2008-12-23 05:35:02 +08:00
|
|
|
OS << " ";
|
|
|
|
PrintRawCXXCatchStmt(Node->getHandler(i));
|
|
|
|
}
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2008-12-23 03:15:10 +08:00
|
|
|
}
|
|
|
|
|
2011-04-28 09:08:34 +08:00
|
|
|
void StmtPrinter::VisitSEHTryStmt(SEHTryStmt *Node) {
|
|
|
|
Indent() << (Node->getIsCXXTry() ? "try " : "__try ");
|
|
|
|
PrintRawCompoundStmt(Node->getTryBlock());
|
|
|
|
SEHExceptStmt *E = Node->getExceptHandler();
|
|
|
|
SEHFinallyStmt *F = Node->getFinallyHandler();
|
|
|
|
if(E)
|
|
|
|
PrintRawSEHExceptHandler(E);
|
|
|
|
else {
|
|
|
|
assert(F && "Must have a finally block...");
|
|
|
|
PrintRawSEHFinallyStmt(F);
|
|
|
|
}
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2011-04-28 09:08:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::PrintRawSEHFinallyStmt(SEHFinallyStmt *Node) {
|
|
|
|
OS << "__finally ";
|
|
|
|
PrintRawCompoundStmt(Node->getBlock());
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2011-04-28 09:08:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::PrintRawSEHExceptHandler(SEHExceptStmt *Node) {
|
|
|
|
OS << "__except (";
|
|
|
|
VisitExpr(Node->getFilterExpr());
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << ")" << NL;
|
2011-04-28 09:08:34 +08:00
|
|
|
PrintRawCompoundStmt(Node->getBlock());
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2011-04-28 09:08:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitSEHExceptStmt(SEHExceptStmt *Node) {
|
|
|
|
Indent();
|
|
|
|
PrintRawSEHExceptHandler(Node);
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2011-04-28 09:08:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) {
|
|
|
|
Indent();
|
|
|
|
PrintRawSEHFinallyStmt(Node);
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2011-04-28 09:08:34 +08:00
|
|
|
}
|
|
|
|
|
2014-07-07 08:12:30 +08:00
|
|
|
void StmtPrinter::VisitSEHLeaveStmt(SEHLeaveStmt *Node) {
|
|
|
|
Indent() << "__leave;";
|
2018-09-15 10:02:31 +08:00
|
|
|
if (Policy.IncludeNewlines) OS << NL;
|
2014-07-07 08:12:30 +08:00
|
|
|
}
|
|
|
|
|
2013-07-19 11:13:43 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OpenMP directives printing methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-11-22 01:08:48 +08:00
|
|
|
void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S,
|
|
|
|
bool ForceNoStmt) {
|
2014-02-13 13:29:23 +08:00
|
|
|
OMPClausePrinter Printer(OS, Policy);
|
2014-02-27 16:29:12 +08:00
|
|
|
ArrayRef<OMPClause *> Clauses = S->clauses();
|
2018-04-11 06:54:42 +08:00
|
|
|
for (auto *Clause : Clauses)
|
|
|
|
if (Clause && !Clause->isImplicit()) {
|
2013-07-19 11:13:43 +08:00
|
|
|
OS << ' ';
|
2018-04-11 06:54:42 +08:00
|
|
|
Printer.Visit(Clause);
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
2018-09-15 10:02:31 +08:00
|
|
|
OS << NL;
|
2018-01-13 03:39:11 +08:00
|
|
|
if (!ForceNoStmt && S->hasAssociatedStmt())
|
|
|
|
PrintStmt(S->getInnermostCapturedStmt()->getCapturedStmt());
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
2014-02-27 16:29:12 +08:00
|
|
|
|
|
|
|
void StmtPrinter::VisitOMPParallelDirective(OMPParallelDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp parallel";
|
2014-02-27 16:29:12 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitOMPSimdDirective(OMPSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp simd";
|
2014-02-27 16:29:12 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-06-18 12:14:57 +08:00
|
|
|
void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp for";
|
2014-06-18 12:14:57 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-09-18 13:12:34 +08:00
|
|
|
void StmtPrinter::VisitOMPForSimdDirective(OMPForSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp for simd";
|
2014-09-18 13:12:34 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-06-25 19:44:49 +08:00
|
|
|
void StmtPrinter::VisitOMPSectionsDirective(OMPSectionsDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp sections";
|
2014-06-25 19:44:49 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-06-26 16:21:58 +08:00
|
|
|
void StmtPrinter::VisitOMPSectionDirective(OMPSectionDirective *Node) {
|
|
|
|
Indent() << "#pragma omp section";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-06-26 20:05:45 +08:00
|
|
|
void StmtPrinter::VisitOMPSingleDirective(OMPSingleDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp single";
|
2014-06-26 20:05:45 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-07-17 16:54:58 +08:00
|
|
|
void StmtPrinter::VisitOMPMasterDirective(OMPMasterDirective *Node) {
|
|
|
|
Indent() << "#pragma omp master";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-07-21 17:42:05 +08:00
|
|
|
void StmtPrinter::VisitOMPCriticalDirective(OMPCriticalDirective *Node) {
|
|
|
|
Indent() << "#pragma omp critical";
|
|
|
|
if (Node->getDirectiveName().getName()) {
|
|
|
|
OS << " (";
|
|
|
|
Node->getDirectiveName().printName(OS);
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-07-07 21:01:15 +08:00
|
|
|
void StmtPrinter::VisitOMPParallelForDirective(OMPParallelForDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp parallel for";
|
2014-07-07 21:01:15 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-09-23 17:33:00 +08:00
|
|
|
void StmtPrinter::VisitOMPParallelForSimdDirective(
|
|
|
|
OMPParallelForSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp parallel for simd";
|
2014-09-23 17:33:00 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-07-08 16:12:03 +08:00
|
|
|
void StmtPrinter::VisitOMPParallelSectionsDirective(
|
|
|
|
OMPParallelSectionsDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp parallel sections";
|
2014-07-08 16:12:03 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-07-11 19:25:16 +08:00
|
|
|
void StmtPrinter::VisitOMPTaskDirective(OMPTaskDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp task";
|
2014-07-11 19:25:16 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-07-18 15:47:19 +08:00
|
|
|
void StmtPrinter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *Node) {
|
|
|
|
Indent() << "#pragma omp taskyield";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-07-18 17:11:51 +08:00
|
|
|
void StmtPrinter::VisitOMPBarrierDirective(OMPBarrierDirective *Node) {
|
|
|
|
Indent() << "#pragma omp barrier";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-07-18 18:17:07 +08:00
|
|
|
void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) {
|
|
|
|
Indent() << "#pragma omp taskwait";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2015-06-18 20:14:09 +08:00
|
|
|
void StmtPrinter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp taskgroup";
|
2015-06-18 20:14:09 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-07-21 19:26:11 +08:00
|
|
|
void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp flush";
|
2014-07-21 19:26:11 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-07-22 14:45:04 +08:00
|
|
|
void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp ordered";
|
2018-01-13 03:39:11 +08:00
|
|
|
PrintOMPExecutableDirective(Node, Node->hasClausesOfKind<OMPDependClause>());
|
2014-07-22 14:45:04 +08:00
|
|
|
}
|
|
|
|
|
2014-07-22 18:10:35 +08:00
|
|
|
void StmtPrinter::VisitOMPAtomicDirective(OMPAtomicDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp atomic";
|
2014-07-22 18:10:35 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-09-19 16:19:49 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetDirective(OMPTargetDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target";
|
2014-09-19 16:19:49 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2015-07-21 21:44:28 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetDataDirective(OMPTargetDataDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target data";
|
2015-07-21 21:44:28 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-01-20 03:15:56 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetEnterDataDirective(
|
|
|
|
OMPTargetEnterDataDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target enter data";
|
2017-11-22 01:08:48 +08:00
|
|
|
PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true);
|
2016-01-20 03:15:56 +08:00
|
|
|
}
|
|
|
|
|
2016-01-20 04:04:50 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetExitDataDirective(
|
|
|
|
OMPTargetExitDataDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target exit data";
|
2017-11-22 01:08:48 +08:00
|
|
|
PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true);
|
2016-01-20 04:04:50 +08:00
|
|
|
}
|
|
|
|
|
2016-01-27 02:48:41 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetParallelDirective(
|
|
|
|
OMPTargetParallelDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target parallel";
|
2016-01-27 02:48:41 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-02-03 23:46:42 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetParallelForDirective(
|
|
|
|
OMPTargetParallelForDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target parallel for";
|
2016-02-03 23:46:42 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2014-10-09 12:18:56 +08:00
|
|
|
void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp teams";
|
2014-10-09 12:18:56 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2015-07-01 14:57:41 +08:00
|
|
|
void StmtPrinter::VisitOMPCancellationPointDirective(
|
|
|
|
OMPCancellationPointDirective *Node) {
|
|
|
|
Indent() << "#pragma omp cancellation point "
|
|
|
|
<< getOpenMPDirectiveName(Node->getCancelRegion());
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
2015-07-02 19:25:17 +08:00
|
|
|
|
|
|
|
void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) {
|
|
|
|
Indent() << "#pragma omp cancel "
|
2018-02-15 01:38:47 +08:00
|
|
|
<< getOpenMPDirectiveName(Node->getCancelRegion());
|
2015-07-02 19:25:17 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
2015-12-01 12:18:41 +08:00
|
|
|
|
|
|
|
void StmtPrinter::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp taskloop";
|
2015-12-01 12:18:41 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2015-12-03 17:40:15 +08:00
|
|
|
void StmtPrinter::VisitOMPTaskLoopSimdDirective(
|
|
|
|
OMPTaskLoopSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp taskloop simd";
|
2015-12-03 17:40:15 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2015-12-14 22:51:25 +08:00
|
|
|
void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp distribute";
|
2015-12-14 22:51:25 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-05-27 01:30:50 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetUpdateDirective(
|
|
|
|
OMPTargetUpdateDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target update";
|
2017-11-22 01:08:48 +08:00
|
|
|
PrintOMPExecutableDirective(Node, /*ForceNoStmt=*/true);
|
2016-05-27 01:30:50 +08:00
|
|
|
}
|
|
|
|
|
2016-06-27 22:55:37 +08:00
|
|
|
void StmtPrinter::VisitOMPDistributeParallelForDirective(
|
|
|
|
OMPDistributeParallelForDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp distribute parallel for";
|
2016-06-27 22:55:37 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-07-05 13:00:15 +08:00
|
|
|
void StmtPrinter::VisitOMPDistributeParallelForSimdDirective(
|
|
|
|
OMPDistributeParallelForSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp distribute parallel for simd";
|
2016-07-05 13:00:15 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-07-06 12:45:38 +08:00
|
|
|
void StmtPrinter::VisitOMPDistributeSimdDirective(
|
|
|
|
OMPDistributeSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp distribute simd";
|
2016-07-06 12:45:38 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-07-14 10:54:56 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetParallelForSimdDirective(
|
|
|
|
OMPTargetParallelForSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target parallel for simd";
|
2016-07-14 10:54:56 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-07-21 06:57:10 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target simd";
|
2016-07-21 06:57:10 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-08-05 22:37:37 +08:00
|
|
|
void StmtPrinter::VisitOMPTeamsDistributeDirective(
|
|
|
|
OMPTeamsDistributeDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp teams distribute";
|
2016-08-05 22:37:37 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-10-25 20:50:55 +08:00
|
|
|
void StmtPrinter::VisitOMPTeamsDistributeSimdDirective(
|
|
|
|
OMPTeamsDistributeSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp teams distribute simd";
|
2016-10-25 20:50:55 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-12-01 07:51:03 +08:00
|
|
|
void StmtPrinter::VisitOMPTeamsDistributeParallelForSimdDirective(
|
|
|
|
OMPTeamsDistributeParallelForSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp teams distribute parallel for simd";
|
2016-12-01 07:51:03 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-12-09 11:24:30 +08:00
|
|
|
void StmtPrinter::VisitOMPTeamsDistributeParallelForDirective(
|
|
|
|
OMPTeamsDistributeParallelForDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp teams distribute parallel for";
|
2016-12-09 11:24:30 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-12-17 13:48:59 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target teams";
|
2016-12-17 13:48:59 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-12-25 12:52:54 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetTeamsDistributeDirective(
|
|
|
|
OMPTargetTeamsDistributeDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target teams distribute";
|
2016-12-25 12:52:54 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2016-12-30 06:16:30 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForDirective(
|
|
|
|
OMPTargetTeamsDistributeParallelForDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target teams distribute parallel for";
|
2016-12-30 06:16:30 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2017-01-03 13:23:48 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForSimdDirective(
|
|
|
|
OMPTargetTeamsDistributeParallelForSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target teams distribute parallel for simd";
|
2017-01-03 13:23:48 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2017-01-11 02:08:18 +08:00
|
|
|
void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective(
|
|
|
|
OMPTargetTeamsDistributeSimdDirective *Node) {
|
2018-02-15 01:38:47 +08:00
|
|
|
Indent() << "#pragma omp target teams distribute simd";
|
2017-01-11 02:08:18 +08:00
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2006-11-05 04:18:38 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Expr printing methods.
|
|
|
|
//===----------------------------------------------------------------------===//
|
2006-11-04 15:16:25 +08:00
|
|
|
|
2018-10-31 11:48:47 +08:00
|
|
|
void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) {
|
|
|
|
PrintExpr(Node->getSubExpr());
|
|
|
|
}
|
|
|
|
|
2006-11-05 02:52:07 +08:00
|
|
|
void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
|
2018-04-11 06:54:42 +08:00
|
|
|
if (const auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) {
|
2016-02-29 13:54:20 +08:00
|
|
|
OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy);
|
|
|
|
return;
|
|
|
|
}
|
2009-10-24 02:54:35 +08:00
|
|
|
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
|
|
|
|
Qualifier->print(OS, Policy);
|
2012-01-27 17:46:47 +08:00
|
|
|
if (Node->hasTemplateKeyword())
|
|
|
|
OS << "template ";
|
2010-08-12 06:01:17 +08:00
|
|
|
OS << Node->getNameInfo();
|
2010-08-20 07:49:38 +08:00
|
|
|
if (Node->hasExplicitTemplateArgs())
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, Node->template_arguments(), Policy);
|
2009-01-06 13:10:23 +08:00
|
|
|
}
|
|
|
|
|
2009-11-20 06:55:06 +08:00
|
|
|
void StmtPrinter::VisitDependentScopeDeclRefExpr(
|
|
|
|
DependentScopeDeclRefExpr *Node) {
|
2011-01-24 23:44:00 +08:00
|
|
|
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
|
|
|
|
Qualifier->print(OS, Policy);
|
2012-01-27 17:46:47 +08:00
|
|
|
if (Node->hasTemplateKeyword())
|
|
|
|
OS << "template ";
|
2010-08-12 06:01:17 +08:00
|
|
|
OS << Node->getNameInfo();
|
2009-11-25 03:00:30 +08:00
|
|
|
if (Node->hasExplicitTemplateArgs())
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, Node->template_arguments(), Policy);
|
Introduce a new expression type, UnresolvedDeclRefExpr, that describes
dependent qualified-ids such as
Fibonacci<N - 1>::value
where N is a template parameter. These references are "unresolved"
because the name is dependent and, therefore, cannot be resolved to a
declaration node (as we would do for a DeclRefExpr or
QualifiedDeclRefExpr). UnresolvedDeclRefExprs instantiate to
DeclRefExprs, QualifiedDeclRefExprs, etc.
Also, be a bit more careful about keeping only a single set of
specializations for a class template, and instantiating from the
definition of that template rather than a previous declaration. In
general, we need a better solution for this for all TagDecls, because
it's too easy to accidentally look at a declaration that isn't the
definition.
We can now process a simple Fibonacci computation described as a
template metaprogram.
llvm-svn: 67308
2009-03-20 01:26:29 +08:00
|
|
|
}
|
|
|
|
|
2009-11-21 16:51:07 +08:00
|
|
|
void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
|
2009-07-01 06:34:41 +08:00
|
|
|
if (Node->getQualifier())
|
|
|
|
Node->getQualifier()->print(OS, Policy);
|
2012-01-27 17:46:47 +08:00
|
|
|
if (Node->hasTemplateKeyword())
|
|
|
|
OS << "template ";
|
2010-08-12 06:01:17 +08:00
|
|
|
OS << Node->getNameInfo();
|
2009-11-25 03:00:30 +08:00
|
|
|
if (Node->hasExplicitTemplateArgs())
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, Node->template_arguments(), Policy);
|
2009-07-01 06:34:41 +08:00
|
|
|
}
|
|
|
|
|
2017-10-26 08:56:54 +08:00
|
|
|
static bool isImplicitSelf(const Expr *E) {
|
|
|
|
if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
|
2018-04-11 06:54:42 +08:00
|
|
|
if (const auto *PD = dyn_cast<ImplicitParamDecl>(DRE->getDecl())) {
|
2017-10-26 08:56:54 +08:00
|
|
|
if (PD->getParameterKind() == ImplicitParamDecl::ObjCSelf &&
|
2018-08-10 05:08:08 +08:00
|
|
|
DRE->getBeginLoc().isInvalid())
|
2017-10-26 08:56:54 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-11-12 22:29:37 +08:00
|
|
|
void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
|
2007-11-13 06:29:28 +08:00
|
|
|
if (Node->getBase()) {
|
2017-10-26 08:56:54 +08:00
|
|
|
if (!Policy.SuppressImplicitBase ||
|
|
|
|
!isImplicitSelf(Node->getBase()->IgnoreImpCasts())) {
|
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << (Node->isArrow() ? "->" : ".");
|
|
|
|
}
|
2007-11-13 06:29:28 +08:00
|
|
|
}
|
2011-10-15 02:45:37 +08:00
|
|
|
OS << *Node->getDecl();
|
2007-11-12 22:29:37 +08:00
|
|
|
}
|
|
|
|
|
2008-05-30 08:40:33 +08:00
|
|
|
void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
|
2010-10-15 00:04:05 +08:00
|
|
|
if (Node->isSuperReceiver())
|
|
|
|
OS << "super.";
|
2014-02-07 07:26:23 +08:00
|
|
|
else if (Node->isObjectReceiver() && Node->getBase()) {
|
2008-05-30 08:40:33 +08:00
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << ".";
|
2014-02-07 07:26:23 +08:00
|
|
|
} else if (Node->isClassReceiver() && Node->getClassReceiver()) {
|
|
|
|
OS << Node->getClassReceiver()->getName() << ".";
|
2008-05-30 08:40:33 +08:00
|
|
|
}
|
2010-10-15 00:04:05 +08:00
|
|
|
|
2018-05-23 08:52:20 +08:00
|
|
|
if (Node->isImplicitProperty()) {
|
|
|
|
if (const auto *Getter = Node->getImplicitPropertyGetter())
|
|
|
|
Getter->getSelector().print(OS);
|
|
|
|
else
|
|
|
|
OS << SelectorTable::getPropertyNameFromSetterSelector(
|
|
|
|
Node->getImplicitPropertySetter()->getSelector());
|
|
|
|
} else
|
2010-12-02 09:19:52 +08:00
|
|
|
OS << Node->getExplicitProperty()->getName();
|
2008-11-23 02:39:36 +08:00
|
|
|
}
|
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
|
|
|
|
PrintExpr(Node->getBaseExpr());
|
|
|
|
OS << "[";
|
|
|
|
PrintExpr(Node->getKeyExpr());
|
|
|
|
OS << "]";
|
|
|
|
}
|
|
|
|
|
2008-08-10 09:53:14 +08:00
|
|
|
void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
|
2018-10-28 03:21:19 +08:00
|
|
|
OS << PredefinedExpr::getIdentKindName(Node->getIdentKind());
|
2007-07-21 13:21:51 +08:00
|
|
|
}
|
|
|
|
|
2007-04-27 04:39:23 +08:00
|
|
|
void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
|
2007-07-13 13:18:11 +08:00
|
|
|
unsigned value = Node->getValue();
|
2011-07-27 13:40:30 +08:00
|
|
|
|
|
|
|
switch (Node->getKind()) {
|
|
|
|
case CharacterLiteral::Ascii: break; // no prefix.
|
|
|
|
case CharacterLiteral::Wide: OS << 'L'; break;
|
2016-01-08 04:59:26 +08:00
|
|
|
case CharacterLiteral::UTF8: OS << "u8"; break;
|
2011-07-27 13:40:30 +08:00
|
|
|
case CharacterLiteral::UTF16: OS << 'u'; break;
|
|
|
|
case CharacterLiteral::UTF32: OS << 'U'; break;
|
|
|
|
}
|
|
|
|
|
2007-07-14 07:58:20 +08:00
|
|
|
switch (value) {
|
|
|
|
case '\\':
|
|
|
|
OS << "'\\\\'";
|
|
|
|
break;
|
|
|
|
case '\'':
|
|
|
|
OS << "'\\''";
|
|
|
|
break;
|
|
|
|
case '\a':
|
|
|
|
// TODO: K&R: the meaning of '\\a' is different in traditional C
|
|
|
|
OS << "'\\a'";
|
|
|
|
break;
|
|
|
|
case '\b':
|
|
|
|
OS << "'\\b'";
|
|
|
|
break;
|
|
|
|
// Nonstandard escape sequence.
|
|
|
|
/*case '\e':
|
|
|
|
OS << "'\\e'";
|
|
|
|
break;*/
|
|
|
|
case '\f':
|
|
|
|
OS << "'\\f'";
|
|
|
|
break;
|
|
|
|
case '\n':
|
|
|
|
OS << "'\\n'";
|
|
|
|
break;
|
|
|
|
case '\r':
|
|
|
|
OS << "'\\r'";
|
|
|
|
break;
|
|
|
|
case '\t':
|
|
|
|
OS << "'\\t'";
|
|
|
|
break;
|
|
|
|
case '\v':
|
|
|
|
OS << "'\\v'";
|
|
|
|
break;
|
|
|
|
default:
|
2016-02-13 10:31:28 +08:00
|
|
|
// A character literal might be sign-extended, which
|
|
|
|
// would result in an invalid \U escape sequence.
|
|
|
|
// FIXME: multicharacter literals such as '\xFF\xFF\xFF\xFF'
|
|
|
|
// are not correctly handled.
|
|
|
|
if ((value & ~0xFFu) == ~0xFFu && Node->getKind() == CharacterLiteral::Ascii)
|
|
|
|
value &= 0xFFu;
|
2013-02-09 06:30:27 +08:00
|
|
|
if (value < 256 && isPrintable((unsigned char)value))
|
2007-07-14 07:58:20 +08:00
|
|
|
OS << "'" << (char)value << "'";
|
2013-02-09 06:30:27 +08:00
|
|
|
else if (value < 256)
|
|
|
|
OS << "'\\x" << llvm::format("%02x", value) << "'";
|
|
|
|
else if (value <= 0xFFFF)
|
|
|
|
OS << "'\\u" << llvm::format("%04x", value) << "'";
|
|
|
|
else
|
|
|
|
OS << "'\\U" << llvm::format("%08x", value) << "'";
|
2007-07-13 13:18:11 +08:00
|
|
|
}
|
2007-04-27 04:39:23 +08:00
|
|
|
}
|
|
|
|
|
2017-08-17 21:41:55 +08:00
|
|
|
/// Prints the given expression using the original source text. Returns true on
|
|
|
|
/// success, false otherwise.
|
|
|
|
static bool printExprAsWritten(raw_ostream &OS, Expr *E,
|
|
|
|
const ASTContext *Context) {
|
|
|
|
if (!Context)
|
|
|
|
return false;
|
|
|
|
bool Invalid = false;
|
|
|
|
StringRef Source = Lexer::getSourceText(
|
|
|
|
CharSourceRange::getTokenRange(E->getSourceRange()),
|
|
|
|
Context->getSourceManager(), Context->getLangOpts(), &Invalid);
|
|
|
|
if (!Invalid) {
|
|
|
|
OS << Source;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-02-22 07:46:25 +08:00
|
|
|
void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
|
2017-08-17 21:41:55 +08:00
|
|
|
if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context))
|
|
|
|
return;
|
2007-05-21 13:45:03 +08:00
|
|
|
bool isSigned = Node->getType()->isSignedIntegerType();
|
|
|
|
OS << Node->getValue().toString(10, isSigned);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-05-21 13:45:03 +08:00
|
|
|
// Emit suffixes. Integer literals are always a builtin integer type.
|
2009-09-22 07:43:11 +08:00
|
|
|
switch (Node->getType()->getAs<BuiltinType>()->getKind()) {
|
2011-09-23 13:06:16 +08:00
|
|
|
default: llvm_unreachable("Unexpected type for integer literal!");
|
2015-03-07 02:04:22 +08:00
|
|
|
case BuiltinType::Char_S:
|
|
|
|
case BuiltinType::Char_U: OS << "i8"; break;
|
2014-06-22 02:46:07 +08:00
|
|
|
case BuiltinType::UChar: OS << "Ui8"; break;
|
|
|
|
case BuiltinType::Short: OS << "i16"; break;
|
|
|
|
case BuiltinType::UShort: OS << "Ui16"; break;
|
2007-05-21 13:45:03 +08:00
|
|
|
case BuiltinType::Int: break; // no suffix.
|
|
|
|
case BuiltinType::UInt: OS << 'U'; break;
|
|
|
|
case BuiltinType::Long: OS << 'L'; break;
|
|
|
|
case BuiltinType::ULong: OS << "UL"; break;
|
|
|
|
case BuiltinType::LongLong: OS << "LL"; break;
|
|
|
|
case BuiltinType::ULongLong: OS << "ULL"; break;
|
|
|
|
}
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
2012-09-20 22:07:17 +08:00
|
|
|
|
2018-06-21 01:19:40 +08:00
|
|
|
void StmtPrinter::VisitFixedPointLiteral(FixedPointLiteral *Node) {
|
|
|
|
if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context))
|
|
|
|
return;
|
|
|
|
OS << Node->getValueAsString(/*Radix=*/10);
|
|
|
|
|
|
|
|
switch (Node->getType()->getAs<BuiltinType>()->getKind()) {
|
|
|
|
default: llvm_unreachable("Unexpected type for fixed point literal!");
|
|
|
|
case BuiltinType::ShortFract: OS << "hr"; break;
|
|
|
|
case BuiltinType::ShortAccum: OS << "hk"; break;
|
|
|
|
case BuiltinType::UShortFract: OS << "uhr"; break;
|
|
|
|
case BuiltinType::UShortAccum: OS << "uhk"; break;
|
|
|
|
case BuiltinType::Fract: OS << "r"; break;
|
|
|
|
case BuiltinType::Accum: OS << "k"; break;
|
|
|
|
case BuiltinType::UFract: OS << "ur"; break;
|
|
|
|
case BuiltinType::UAccum: OS << "uk"; break;
|
|
|
|
case BuiltinType::LongFract: OS << "lr"; break;
|
|
|
|
case BuiltinType::LongAccum: OS << "lk"; break;
|
|
|
|
case BuiltinType::ULongFract: OS << "ulr"; break;
|
|
|
|
case BuiltinType::ULongAccum: OS << "ulk"; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-20 22:07:17 +08:00
|
|
|
static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
|
|
|
|
bool PrintSuffix) {
|
2012-02-05 10:13:05 +08:00
|
|
|
SmallString<16> Str;
|
2011-10-06 04:32:03 +08:00
|
|
|
Node->getValue().toString(Str);
|
|
|
|
OS << Str;
|
2012-09-20 22:07:17 +08:00
|
|
|
if (Str.find_first_not_of("-0123456789") == StringRef::npos)
|
|
|
|
OS << '.'; // Trailing dot in order to separate from ints.
|
|
|
|
|
|
|
|
if (!PrintSuffix)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Emit suffixes. Float literals are always a builtin float type.
|
|
|
|
switch (Node->getType()->getAs<BuiltinType>()->getKind()) {
|
|
|
|
default: llvm_unreachable("Unexpected type for float literal!");
|
|
|
|
case BuiltinType::Half: break; // FIXME: suffix?
|
|
|
|
case BuiltinType::Double: break; // no suffix.
|
2017-09-08 23:15:00 +08:00
|
|
|
case BuiltinType::Float16: OS << "F16"; break;
|
2012-09-20 22:07:17 +08:00
|
|
|
case BuiltinType::Float: OS << 'F'; break;
|
|
|
|
case BuiltinType::LongDouble: OS << 'L'; break;
|
2016-05-09 16:52:33 +08:00
|
|
|
case BuiltinType::Float128: OS << 'Q'; break;
|
2012-09-20 22:07:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) {
|
2017-08-17 21:41:55 +08:00
|
|
|
if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context))
|
|
|
|
return;
|
2012-09-20 22:07:17 +08:00
|
|
|
PrintFloatingLiteral(OS, Node, /*PrintSuffix=*/true);
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
2007-08-26 11:42:43 +08:00
|
|
|
|
|
|
|
void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) {
|
|
|
|
PrintExpr(Node->getSubExpr());
|
|
|
|
OS << "i";
|
|
|
|
}
|
|
|
|
|
2007-02-22 07:46:25 +08:00
|
|
|
void StmtPrinter::VisitStringLiteral(StringLiteral *Str) {
|
2012-06-14 04:25:24 +08:00
|
|
|
Str->outputString(OS);
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2006-11-05 02:52:07 +08:00
|
|
|
void StmtPrinter::VisitParenExpr(ParenExpr *Node) {
|
|
|
|
OS << "(";
|
|
|
|
PrintExpr(Node->getSubExpr());
|
2007-06-01 02:21:33 +08:00
|
|
|
OS << ")";
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2006-11-05 02:52:07 +08:00
|
|
|
void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
|
2007-08-24 05:46:40 +08:00
|
|
|
if (!Node->isPostfix()) {
|
2006-11-06 07:54:51 +08:00
|
|
|
OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-15 06:39:26 +08:00
|
|
|
// Print a space if this is an "identifier operator" like __real, or if
|
|
|
|
// it might be concatenated incorrectly like '+'.
|
2007-08-24 05:46:40 +08:00
|
|
|
switch (Node->getOpcode()) {
|
|
|
|
default: break;
|
2010-08-25 19:45:40 +08:00
|
|
|
case UO_Real:
|
|
|
|
case UO_Imag:
|
|
|
|
case UO_Extension:
|
2007-08-24 05:46:40 +08:00
|
|
|
OS << ' ';
|
|
|
|
break;
|
2010-08-25 19:45:40 +08:00
|
|
|
case UO_Plus:
|
|
|
|
case UO_Minus:
|
2009-06-15 06:39:26 +08:00
|
|
|
if (isa<UnaryOperator>(Node->getSubExpr()))
|
|
|
|
OS << ' ';
|
|
|
|
break;
|
2007-08-24 05:46:40 +08:00
|
|
|
}
|
|
|
|
}
|
2006-11-05 02:52:07 +08:00
|
|
|
PrintExpr(Node->getSubExpr());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-11-06 07:54:51 +08:00
|
|
|
if (Node->isPostfix())
|
|
|
|
OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
|
2007-08-31 01:59:59 +08:00
|
|
|
}
|
|
|
|
|
Completely reimplement __builtin_offsetof, based on a patch by Roberto
Amadini.
This change introduces a new expression node type, OffsetOfExpr, that
describes __builtin_offsetof. Previously, __builtin_offsetof was
implemented using a unary operator whose subexpression involved
various synthesized array-subscript and member-reference expressions,
which was ugly and made it very hard to instantiate as a
template. OffsetOfExpr represents the AST more faithfully, with proper
type source information and a more compact representation.
OffsetOfExpr also has support for dependent __builtin_offsetof
expressions; it can be value-dependent, but will never be
type-dependent (like sizeof or alignof). This commit introduces
template instantiation for __builtin_offsetof as well.
There are two major caveats to this patch:
1) CodeGen cannot handle the case where __builtin_offsetof is not a
constant expression, so it produces an error. So, to avoid
regressing in C, we retain the old UnaryOperator-based
__builtin_offsetof implementation in C while using the shiny new
OffsetOfExpr implementation in C++. The old implementation can go
away once we have proper CodeGen support for this case, which we
expect won't cause much trouble in C++.
2) __builtin_offsetof doesn't work well with non-POD class types,
particularly when the designated field is found within a base
class. I will address this in a subsequent patch.
Fixes PR5880 and a bunch of assertions when building Boost.Python
tests.
llvm-svn: 102542
2010-04-29 06:16:22 +08:00
|
|
|
void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
|
|
|
|
OS << "__builtin_offsetof(";
|
2013-02-22 22:19:01 +08:00
|
|
|
Node->getTypeSourceInfo()->getType().print(OS, Policy);
|
|
|
|
OS << ", ";
|
Completely reimplement __builtin_offsetof, based on a patch by Roberto
Amadini.
This change introduces a new expression node type, OffsetOfExpr, that
describes __builtin_offsetof. Previously, __builtin_offsetof was
implemented using a unary operator whose subexpression involved
various synthesized array-subscript and member-reference expressions,
which was ugly and made it very hard to instantiate as a
template. OffsetOfExpr represents the AST more faithfully, with proper
type source information and a more compact representation.
OffsetOfExpr also has support for dependent __builtin_offsetof
expressions; it can be value-dependent, but will never be
type-dependent (like sizeof or alignof). This commit introduces
template instantiation for __builtin_offsetof as well.
There are two major caveats to this patch:
1) CodeGen cannot handle the case where __builtin_offsetof is not a
constant expression, so it produces an error. So, to avoid
regressing in C, we retain the old UnaryOperator-based
__builtin_offsetof implementation in C while using the shiny new
OffsetOfExpr implementation in C++. The old implementation can go
away once we have proper CodeGen support for this case, which we
expect won't cause much trouble in C++.
2) __builtin_offsetof doesn't work well with non-POD class types,
particularly when the designated field is found within a base
class. I will address this in a subsequent patch.
Fixes PR5880 and a bunch of assertions when building Boost.Python
tests.
llvm-svn: 102542
2010-04-29 06:16:22 +08:00
|
|
|
bool PrintedSomething = false;
|
|
|
|
for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) {
|
2015-12-30 06:31:18 +08:00
|
|
|
OffsetOfNode ON = Node->getComponent(i);
|
|
|
|
if (ON.getKind() == OffsetOfNode::Array) {
|
Completely reimplement __builtin_offsetof, based on a patch by Roberto
Amadini.
This change introduces a new expression node type, OffsetOfExpr, that
describes __builtin_offsetof. Previously, __builtin_offsetof was
implemented using a unary operator whose subexpression involved
various synthesized array-subscript and member-reference expressions,
which was ugly and made it very hard to instantiate as a
template. OffsetOfExpr represents the AST more faithfully, with proper
type source information and a more compact representation.
OffsetOfExpr also has support for dependent __builtin_offsetof
expressions; it can be value-dependent, but will never be
type-dependent (like sizeof or alignof). This commit introduces
template instantiation for __builtin_offsetof as well.
There are two major caveats to this patch:
1) CodeGen cannot handle the case where __builtin_offsetof is not a
constant expression, so it produces an error. So, to avoid
regressing in C, we retain the old UnaryOperator-based
__builtin_offsetof implementation in C while using the shiny new
OffsetOfExpr implementation in C++. The old implementation can go
away once we have proper CodeGen support for this case, which we
expect won't cause much trouble in C++.
2) __builtin_offsetof doesn't work well with non-POD class types,
particularly when the designated field is found within a base
class. I will address this in a subsequent patch.
Fixes PR5880 and a bunch of assertions when building Boost.Python
tests.
llvm-svn: 102542
2010-04-29 06:16:22 +08:00
|
|
|
// Array node
|
|
|
|
OS << "[";
|
|
|
|
PrintExpr(Node->getIndexExpr(ON.getArrayExprIndex()));
|
|
|
|
OS << "]";
|
|
|
|
PrintedSomething = true;
|
|
|
|
continue;
|
|
|
|
}
|
2010-04-29 08:18:15 +08:00
|
|
|
|
|
|
|
// Skip implicit base indirections.
|
2015-12-30 06:31:18 +08:00
|
|
|
if (ON.getKind() == OffsetOfNode::Base)
|
2010-04-29 08:18:15 +08:00
|
|
|
continue;
|
|
|
|
|
Completely reimplement __builtin_offsetof, based on a patch by Roberto
Amadini.
This change introduces a new expression node type, OffsetOfExpr, that
describes __builtin_offsetof. Previously, __builtin_offsetof was
implemented using a unary operator whose subexpression involved
various synthesized array-subscript and member-reference expressions,
which was ugly and made it very hard to instantiate as a
template. OffsetOfExpr represents the AST more faithfully, with proper
type source information and a more compact representation.
OffsetOfExpr also has support for dependent __builtin_offsetof
expressions; it can be value-dependent, but will never be
type-dependent (like sizeof or alignof). This commit introduces
template instantiation for __builtin_offsetof as well.
There are two major caveats to this patch:
1) CodeGen cannot handle the case where __builtin_offsetof is not a
constant expression, so it produces an error. So, to avoid
regressing in C, we retain the old UnaryOperator-based
__builtin_offsetof implementation in C while using the shiny new
OffsetOfExpr implementation in C++. The old implementation can go
away once we have proper CodeGen support for this case, which we
expect won't cause much trouble in C++.
2) __builtin_offsetof doesn't work well with non-POD class types,
particularly when the designated field is found within a base
class. I will address this in a subsequent patch.
Fixes PR5880 and a bunch of assertions when building Boost.Python
tests.
llvm-svn: 102542
2010-04-29 06:16:22 +08:00
|
|
|
// Field or identifier node.
|
|
|
|
IdentifierInfo *Id = ON.getFieldName();
|
|
|
|
if (!Id)
|
|
|
|
continue;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
Completely reimplement __builtin_offsetof, based on a patch by Roberto
Amadini.
This change introduces a new expression node type, OffsetOfExpr, that
describes __builtin_offsetof. Previously, __builtin_offsetof was
implemented using a unary operator whose subexpression involved
various synthesized array-subscript and member-reference expressions,
which was ugly and made it very hard to instantiate as a
template. OffsetOfExpr represents the AST more faithfully, with proper
type source information and a more compact representation.
OffsetOfExpr also has support for dependent __builtin_offsetof
expressions; it can be value-dependent, but will never be
type-dependent (like sizeof or alignof). This commit introduces
template instantiation for __builtin_offsetof as well.
There are two major caveats to this patch:
1) CodeGen cannot handle the case where __builtin_offsetof is not a
constant expression, so it produces an error. So, to avoid
regressing in C, we retain the old UnaryOperator-based
__builtin_offsetof implementation in C while using the shiny new
OffsetOfExpr implementation in C++. The old implementation can go
away once we have proper CodeGen support for this case, which we
expect won't cause much trouble in C++.
2) __builtin_offsetof doesn't work well with non-POD class types,
particularly when the designated field is found within a base
class. I will address this in a subsequent patch.
Fixes PR5880 and a bunch of assertions when building Boost.Python
tests.
llvm-svn: 102542
2010-04-29 06:16:22 +08:00
|
|
|
if (PrintedSomething)
|
|
|
|
OS << ".";
|
|
|
|
else
|
|
|
|
PrintedSomething = true;
|
2018-07-31 03:24:48 +08:00
|
|
|
OS << Id->getName();
|
Completely reimplement __builtin_offsetof, based on a patch by Roberto
Amadini.
This change introduces a new expression node type, OffsetOfExpr, that
describes __builtin_offsetof. Previously, __builtin_offsetof was
implemented using a unary operator whose subexpression involved
various synthesized array-subscript and member-reference expressions,
which was ugly and made it very hard to instantiate as a
template. OffsetOfExpr represents the AST more faithfully, with proper
type source information and a more compact representation.
OffsetOfExpr also has support for dependent __builtin_offsetof
expressions; it can be value-dependent, but will never be
type-dependent (like sizeof or alignof). This commit introduces
template instantiation for __builtin_offsetof as well.
There are two major caveats to this patch:
1) CodeGen cannot handle the case where __builtin_offsetof is not a
constant expression, so it produces an error. So, to avoid
regressing in C, we retain the old UnaryOperator-based
__builtin_offsetof implementation in C while using the shiny new
OffsetOfExpr implementation in C++. The old implementation can go
away once we have proper CodeGen support for this case, which we
expect won't cause much trouble in C++.
2) __builtin_offsetof doesn't work well with non-POD class types,
particularly when the designated field is found within a base
class. I will address this in a subsequent patch.
Fixes PR5880 and a bunch of assertions when building Boost.Python
tests.
llvm-svn: 102542
2010-04-29 06:16:22 +08:00
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2011-03-12 03:24:49 +08:00
|
|
|
void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){
|
|
|
|
switch(Node->getKind()) {
|
|
|
|
case UETT_SizeOf:
|
|
|
|
OS << "sizeof";
|
|
|
|
break;
|
|
|
|
case UETT_AlignOf:
|
2016-05-19 09:39:10 +08:00
|
|
|
if (Policy.Alignof)
|
2012-07-01 05:33:57 +08:00
|
|
|
OS << "alignof";
|
2016-05-19 09:39:10 +08:00
|
|
|
else if (Policy.UnderscoreAlignof)
|
2012-07-01 05:33:57 +08:00
|
|
|
OS << "_Alignof";
|
|
|
|
else
|
|
|
|
OS << "__alignof";
|
2011-03-12 03:24:49 +08:00
|
|
|
break;
|
2018-10-27 03:26:45 +08:00
|
|
|
case UETT_PreferredAlignOf:
|
|
|
|
OS << "__alignof";
|
|
|
|
break;
|
2011-03-12 03:24:49 +08:00
|
|
|
case UETT_VecStep:
|
|
|
|
OS << "vec_step";
|
|
|
|
break;
|
2015-07-02 11:40:19 +08:00
|
|
|
case UETT_OpenMPRequiredSimdAlign:
|
|
|
|
OS << "__builtin_omp_required_simd_align";
|
|
|
|
break;
|
2011-03-12 03:24:49 +08:00
|
|
|
}
|
2013-02-22 22:19:01 +08:00
|
|
|
if (Node->isArgumentType()) {
|
|
|
|
OS << '(';
|
|
|
|
Node->getArgumentType().print(OS, Policy);
|
|
|
|
OS << ')';
|
|
|
|
} else {
|
2008-11-12 01:56:53 +08:00
|
|
|
OS << " ";
|
|
|
|
PrintExpr(Node->getArgumentExpr());
|
|
|
|
}
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
2011-04-15 08:35:48 +08:00
|
|
|
|
|
|
|
void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) {
|
|
|
|
OS << "_Generic(";
|
|
|
|
PrintExpr(Node->getControllingExpr());
|
2019-01-29 20:57:11 +08:00
|
|
|
for (const GenericSelectionExpr::Association &Assoc : Node->associations()) {
|
2011-04-15 08:35:48 +08:00
|
|
|
OS << ", ";
|
2019-01-29 20:57:11 +08:00
|
|
|
QualType T = Assoc.getType();
|
2011-04-15 08:35:48 +08:00
|
|
|
if (T.isNull())
|
|
|
|
OS << "default";
|
|
|
|
else
|
2013-02-22 22:19:01 +08:00
|
|
|
T.print(OS, Policy);
|
2011-04-15 08:35:48 +08:00
|
|
|
OS << ": ";
|
2019-01-29 20:57:11 +08:00
|
|
|
PrintExpr(Assoc.getAssociationExpr());
|
2011-04-15 08:35:48 +08:00
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2006-11-05 02:52:07 +08:00
|
|
|
void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) {
|
2007-08-21 00:18:38 +08:00
|
|
|
PrintExpr(Node->getLHS());
|
2006-11-05 02:52:07 +08:00
|
|
|
OS << "[";
|
2007-08-21 00:18:38 +08:00
|
|
|
PrintExpr(Node->getRHS());
|
2006-11-05 02:52:07 +08:00
|
|
|
OS << "]";
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
|
|
|
|
2015-08-25 22:24:04 +08:00
|
|
|
void StmtPrinter::VisitOMPArraySectionExpr(OMPArraySectionExpr *Node) {
|
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << "[";
|
|
|
|
if (Node->getLowerBound())
|
|
|
|
PrintExpr(Node->getLowerBound());
|
2015-09-11 12:54:28 +08:00
|
|
|
if (Node->getColonLoc().isValid()) {
|
|
|
|
OS << ":";
|
|
|
|
if (Node->getLength())
|
|
|
|
PrintExpr(Node->getLength());
|
|
|
|
}
|
2015-08-25 22:24:04 +08:00
|
|
|
OS << "]";
|
|
|
|
}
|
|
|
|
|
2011-02-09 05:17:54 +08:00
|
|
|
void StmtPrinter::PrintCallArgs(CallExpr *Call) {
|
2006-11-05 02:52:07 +08:00
|
|
|
for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) {
|
2008-04-08 12:40:51 +08:00
|
|
|
if (isa<CXXDefaultArgExpr>(Call->getArg(i))) {
|
|
|
|
// Don't print any defaulted arguments
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-11-05 02:52:07 +08:00
|
|
|
if (i) OS << ", ";
|
|
|
|
PrintExpr(Call->getArg(i));
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
2011-02-09 05:17:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCallExpr(CallExpr *Call) {
|
|
|
|
PrintExpr(Call->getCallee());
|
|
|
|
OS << "(";
|
|
|
|
PrintCallArgs(Call);
|
2006-11-05 02:52:07 +08:00
|
|
|
OS << ")";
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
2017-10-26 08:56:54 +08:00
|
|
|
|
|
|
|
static bool isImplicitThis(const Expr *E) {
|
|
|
|
if (const auto *TE = dyn_cast<CXXThisExpr>(E))
|
|
|
|
return TE->isImplicit();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-11-05 02:52:07 +08:00
|
|
|
void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
|
2017-10-26 08:56:54 +08:00
|
|
|
if (!Policy.SuppressImplicitBase || !isImplicitThis(Node->getBase())) {
|
|
|
|
PrintExpr(Node->getBase());
|
2012-11-13 03:12:12 +08:00
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
auto *ParentMember = dyn_cast<MemberExpr>(Node->getBase());
|
2017-10-26 08:56:54 +08:00
|
|
|
FieldDecl *ParentDecl =
|
|
|
|
ParentMember ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl())
|
|
|
|
: nullptr;
|
2012-11-13 03:12:12 +08:00
|
|
|
|
2017-10-26 08:56:54 +08:00
|
|
|
if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion())
|
|
|
|
OS << (Node->isArrow() ? "->" : ".");
|
|
|
|
}
|
2012-11-13 03:12:12 +08:00
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
if (auto *FD = dyn_cast<FieldDecl>(Node->getMemberDecl()))
|
2010-01-12 05:17:32 +08:00
|
|
|
if (FD->isAnonymousStructOrUnion())
|
|
|
|
return;
|
2012-11-13 03:12:12 +08:00
|
|
|
|
2009-09-01 07:41:50 +08:00
|
|
|
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
|
|
|
|
Qualifier->print(OS, Policy);
|
2012-01-27 17:46:47 +08:00
|
|
|
if (Node->hasTemplateKeyword())
|
|
|
|
OS << "template ";
|
2010-08-12 06:01:17 +08:00
|
|
|
OS << Node->getMemberNameInfo();
|
2010-08-20 07:49:38 +08:00
|
|
|
if (Node->hasExplicitTemplateArgs())
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, Node->template_arguments(), Policy);
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2009-07-25 01:54:45 +08:00
|
|
|
void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
|
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << (Node->isArrow() ? "->isa" : ".isa");
|
|
|
|
}
|
|
|
|
|
2008-04-19 07:10:10 +08:00
|
|
|
void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
|
2007-07-29 07:10:27 +08:00
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << ".";
|
|
|
|
OS << Node->getAccessor().getName();
|
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2008-10-28 23:36:24 +08:00
|
|
|
void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
|
2013-02-22 22:19:01 +08:00
|
|
|
OS << '(';
|
|
|
|
Node->getTypeAsWritten().print(OS, Policy);
|
|
|
|
OS << ')';
|
2006-11-05 02:52:07 +08:00
|
|
|
PrintExpr(Node->getSubExpr());
|
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2007-07-20 05:32:11 +08:00
|
|
|
void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) {
|
2013-02-22 22:19:01 +08:00
|
|
|
OS << '(';
|
|
|
|
Node->getType().print(OS, Policy);
|
|
|
|
OS << ')';
|
2007-07-20 05:32:11 +08:00
|
|
|
PrintExpr(Node->getInitializer());
|
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2007-07-14 00:58:59 +08:00
|
|
|
void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
|
2013-12-07 01:56:43 +08:00
|
|
|
// No need to print anything, simply forward to the subexpression.
|
2007-07-14 07:32:42 +08:00
|
|
|
PrintExpr(Node->getSubExpr());
|
2007-07-14 00:58:59 +08:00
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2006-11-05 02:52:07 +08:00
|
|
|
void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) {
|
|
|
|
PrintExpr(Node->getLHS());
|
|
|
|
OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " ";
|
2007-08-25 10:00:02 +08:00
|
|
|
PrintExpr(Node->getRHS());
|
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2007-08-25 10:00:02 +08:00
|
|
|
void StmtPrinter::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
|
|
|
|
PrintExpr(Node->getLHS());
|
|
|
|
OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " ";
|
2006-11-05 02:52:07 +08:00
|
|
|
PrintExpr(Node->getRHS());
|
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2006-11-05 02:52:07 +08:00
|
|
|
void StmtPrinter::VisitConditionalOperator(ConditionalOperator *Node) {
|
|
|
|
PrintExpr(Node->getCond());
|
2011-02-17 18:25:35 +08:00
|
|
|
OS << " ? ";
|
|
|
|
PrintExpr(Node->getLHS());
|
|
|
|
OS << " : ";
|
2006-11-05 02:52:07 +08:00
|
|
|
PrintExpr(Node->getRHS());
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
|
|
|
|
2007-05-28 14:56:27 +08:00
|
|
|
// GNU extensions.
|
|
|
|
|
2011-02-17 18:25:35 +08:00
|
|
|
void
|
|
|
|
StmtPrinter::VisitBinaryConditionalOperator(BinaryConditionalOperator *Node) {
|
|
|
|
PrintExpr(Node->getCommon());
|
|
|
|
OS << " ?: ";
|
|
|
|
PrintExpr(Node->getFalseExpr());
|
|
|
|
}
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2007-08-04 01:31:20 +08:00
|
|
|
void StmtPrinter::VisitAddrLabelExpr(AddrLabelExpr *Node) {
|
2007-05-28 14:56:27 +08:00
|
|
|
OS << "&&" << Node->getLabel()->getName();
|
|
|
|
}
|
|
|
|
|
2007-07-25 00:58:17 +08:00
|
|
|
void StmtPrinter::VisitStmtExpr(StmtExpr *E) {
|
|
|
|
OS << "(";
|
|
|
|
PrintRawCompoundStmt(E->getSubStmt());
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2007-08-04 05:21:27 +08:00
|
|
|
void StmtPrinter::VisitChooseExpr(ChooseExpr *Node) {
|
|
|
|
OS << "__builtin_choose_expr(";
|
|
|
|
PrintExpr(Node->getCond());
|
2007-08-04 08:20:15 +08:00
|
|
|
OS << ", ";
|
2007-08-04 05:21:27 +08:00
|
|
|
PrintExpr(Node->getLHS());
|
2007-08-04 08:20:15 +08:00
|
|
|
OS << ", ";
|
2007-08-04 05:21:27 +08:00
|
|
|
PrintExpr(Node->getRHS());
|
|
|
|
OS << ")";
|
|
|
|
}
|
2007-07-25 00:58:17 +08:00
|
|
|
|
2008-11-29 12:51:27 +08:00
|
|
|
void StmtPrinter::VisitGNUNullExpr(GNUNullExpr *) {
|
|
|
|
OS << "__null";
|
|
|
|
}
|
|
|
|
|
2008-05-15 03:38:39 +08:00
|
|
|
void StmtPrinter::VisitShuffleVectorExpr(ShuffleVectorExpr *Node) {
|
|
|
|
OS << "__builtin_shufflevector(";
|
|
|
|
for (unsigned i = 0, e = Node->getNumSubExprs(); i != e; ++i) {
|
|
|
|
if (i) OS << ", ";
|
|
|
|
PrintExpr(Node->getExpr(i));
|
|
|
|
}
|
|
|
|
OS << ")";
|
2008-01-18 01:46:27 +08:00
|
|
|
}
|
|
|
|
|
2013-09-18 11:29:45 +08:00
|
|
|
void StmtPrinter::VisitConvertVectorExpr(ConvertVectorExpr *Node) {
|
|
|
|
OS << "__builtin_convertvector(";
|
|
|
|
PrintExpr(Node->getSrcExpr());
|
|
|
|
OS << ", ";
|
|
|
|
Node->getType().print(OS, Policy);
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2007-08-31 12:56:16 +08:00
|
|
|
void StmtPrinter::VisitInitListExpr(InitListExpr* Node) {
|
2009-05-30 08:56:08 +08:00
|
|
|
if (Node->getSyntacticForm()) {
|
|
|
|
Visit(Node->getSyntacticForm());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-01-30 10:04:26 +08:00
|
|
|
OS << "{";
|
2007-08-31 12:56:16 +08:00
|
|
|
for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) {
|
|
|
|
if (i) OS << ", ";
|
2009-01-29 05:54:33 +08:00
|
|
|
if (Node->getInit(i))
|
|
|
|
PrintExpr(Node->getInit(i));
|
|
|
|
else
|
2015-01-30 10:04:26 +08:00
|
|
|
OS << "{}";
|
2007-08-31 12:56:16 +08:00
|
|
|
}
|
2015-01-30 10:04:26 +08:00
|
|
|
OS << "}";
|
2007-08-31 12:56:16 +08:00
|
|
|
}
|
|
|
|
|
2016-12-12 10:53:20 +08:00
|
|
|
void StmtPrinter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *Node) {
|
|
|
|
// There's no way to express this expression in any of our supported
|
|
|
|
// languages, so just emit something terse and (hopefully) clear.
|
|
|
|
OS << "{";
|
|
|
|
PrintExpr(Node->getSubExpr());
|
|
|
|
OS << "}";
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *Node) {
|
|
|
|
OS << "*";
|
|
|
|
}
|
|
|
|
|
2009-08-11 07:49:36 +08:00
|
|
|
void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) {
|
2015-01-30 10:04:26 +08:00
|
|
|
OS << "(";
|
2009-08-11 07:49:36 +08:00
|
|
|
for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) {
|
|
|
|
if (i) OS << ", ";
|
|
|
|
PrintExpr(Node->getExpr(i));
|
|
|
|
}
|
2015-01-30 10:04:26 +08:00
|
|
|
OS << ")";
|
2009-08-11 07:49:36 +08:00
|
|
|
}
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) {
|
2015-05-29 06:19:36 +08:00
|
|
|
bool NeedsEquals = true;
|
2016-06-23 08:15:04 +08:00
|
|
|
for (const DesignatedInitExpr::Designator &D : Node->designators()) {
|
|
|
|
if (D.isFieldDesignator()) {
|
|
|
|
if (D.getDotLoc().isInvalid()) {
|
|
|
|
if (IdentifierInfo *II = D.getFieldName()) {
|
2014-06-21 01:08:28 +08:00
|
|
|
OS << II->getName() << ":";
|
2015-05-29 06:19:36 +08:00
|
|
|
NeedsEquals = false;
|
|
|
|
}
|
2014-06-21 01:08:28 +08:00
|
|
|
} else {
|
2016-06-23 08:15:04 +08:00
|
|
|
OS << "." << D.getFieldName()->getName();
|
2014-06-21 01:08:28 +08:00
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
} else {
|
|
|
|
OS << "[";
|
2016-06-23 08:15:04 +08:00
|
|
|
if (D.isArrayDesignator()) {
|
|
|
|
PrintExpr(Node->getArrayIndex(D));
|
2009-01-29 05:54:33 +08:00
|
|
|
} else {
|
2016-06-23 08:15:04 +08:00
|
|
|
PrintExpr(Node->getArrayRangeStart(D));
|
2009-01-29 05:54:33 +08:00
|
|
|
OS << " ... ";
|
2016-06-23 08:15:04 +08:00
|
|
|
PrintExpr(Node->getArrayRangeEnd(D));
|
2009-01-29 05:54:33 +08:00
|
|
|
}
|
|
|
|
OS << "]";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-29 06:19:36 +08:00
|
|
|
if (NeedsEquals)
|
|
|
|
OS << " = ";
|
|
|
|
else
|
|
|
|
OS << " ";
|
2009-01-29 05:54:33 +08:00
|
|
|
PrintExpr(Node->getInit());
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
|
|
|
|
2015-06-10 08:27:52 +08:00
|
|
|
void StmtPrinter::VisitDesignatedInitUpdateExpr(
|
|
|
|
DesignatedInitUpdateExpr *Node) {
|
|
|
|
OS << "{";
|
|
|
|
OS << "/*base*/";
|
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << ", ";
|
|
|
|
|
|
|
|
OS << "/*updater*/";
|
|
|
|
PrintExpr(Node->getUpdater());
|
|
|
|
OS << "}";
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitNoInitExpr(NoInitExpr *Node) {
|
|
|
|
OS << "/*no init*/";
|
|
|
|
}
|
|
|
|
|
2009-01-30 01:44:32 +08:00
|
|
|
void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) {
|
2016-05-19 09:39:10 +08:00
|
|
|
if (Node->getType()->getAsCXXRecordDecl()) {
|
2013-02-22 22:19:01 +08:00
|
|
|
OS << "/*implicit*/";
|
|
|
|
Node->getType().print(OS, Policy);
|
|
|
|
OS << "()";
|
|
|
|
} else {
|
|
|
|
OS << "/*implicit*/(";
|
|
|
|
Node->getType().print(OS, Policy);
|
|
|
|
OS << ')';
|
2009-05-30 08:08:05 +08:00
|
|
|
if (Node->getType()->isRecordType())
|
|
|
|
OS << "{}";
|
|
|
|
else
|
|
|
|
OS << 0;
|
|
|
|
}
|
2009-01-30 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
2007-10-16 04:28:48 +08:00
|
|
|
void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) {
|
2009-05-30 12:20:30 +08:00
|
|
|
OS << "__builtin_va_arg(";
|
2007-10-16 04:28:48 +08:00
|
|
|
PrintExpr(Node->getSubExpr());
|
|
|
|
OS << ", ";
|
2013-02-22 22:19:01 +08:00
|
|
|
Node->getType().print(OS, Policy);
|
2007-10-16 04:28:48 +08:00
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2011-11-06 17:01:30 +08:00
|
|
|
void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) {
|
|
|
|
PrintExpr(Node->getSyntacticForm());
|
|
|
|
}
|
|
|
|
|
2011-10-11 10:20:01 +08:00
|
|
|
void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
|
2014-05-12 13:36:57 +08:00
|
|
|
const char *Name = nullptr;
|
2011-10-11 10:20:01 +08:00
|
|
|
switch (Node->getOp()) {
|
2012-04-12 13:08:17 +08:00
|
|
|
#define BUILTIN(ID, TYPE, ATTRS)
|
|
|
|
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
|
|
|
|
case AtomicExpr::AO ## ID: \
|
|
|
|
Name = #ID "("; \
|
|
|
|
break;
|
|
|
|
#include "clang/Basic/Builtins.def"
|
2011-10-11 10:20:01 +08:00
|
|
|
}
|
|
|
|
OS << Name;
|
2012-04-12 13:08:17 +08:00
|
|
|
|
|
|
|
// AtomicExpr stores its subexpressions in a permuted order.
|
2011-10-11 10:20:01 +08:00
|
|
|
PrintExpr(Node->getPtr());
|
2012-04-12 13:08:17 +08:00
|
|
|
if (Node->getOp() != AtomicExpr::AO__c11_atomic_load &&
|
2017-08-05 02:16:31 +08:00
|
|
|
Node->getOp() != AtomicExpr::AO__atomic_load_n &&
|
|
|
|
Node->getOp() != AtomicExpr::AO__opencl_atomic_load) {
|
2011-10-11 10:20:01 +08:00
|
|
|
OS << ", ";
|
2013-05-02 03:02:43 +08:00
|
|
|
PrintExpr(Node->getVal1());
|
2011-10-11 10:20:01 +08:00
|
|
|
}
|
2012-04-12 13:08:17 +08:00
|
|
|
if (Node->getOp() == AtomicExpr::AO__atomic_exchange ||
|
|
|
|
Node->isCmpXChg()) {
|
2011-10-11 10:20:01 +08:00
|
|
|
OS << ", ";
|
2013-05-02 03:02:43 +08:00
|
|
|
PrintExpr(Node->getVal2());
|
2011-10-11 10:20:01 +08:00
|
|
|
}
|
2012-04-12 13:08:17 +08:00
|
|
|
if (Node->getOp() == AtomicExpr::AO__atomic_compare_exchange ||
|
|
|
|
Node->getOp() == AtomicExpr::AO__atomic_compare_exchange_n) {
|
|
|
|
OS << ", ";
|
2013-05-02 03:02:43 +08:00
|
|
|
PrintExpr(Node->getWeak());
|
2012-04-12 13:08:17 +08:00
|
|
|
}
|
2017-08-05 02:16:31 +08:00
|
|
|
if (Node->getOp() != AtomicExpr::AO__c11_atomic_init &&
|
|
|
|
Node->getOp() != AtomicExpr::AO__opencl_atomic_init) {
|
2013-05-02 03:02:43 +08:00
|
|
|
OS << ", ";
|
2012-01-17 01:27:18 +08:00
|
|
|
PrintExpr(Node->getOrder());
|
2013-05-02 03:02:43 +08:00
|
|
|
}
|
2011-10-11 10:20:01 +08:00
|
|
|
if (Node->isCmpXChg()) {
|
|
|
|
OS << ", ";
|
|
|
|
PrintExpr(Node->getOrderFail());
|
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2007-05-28 14:56:27 +08:00
|
|
|
// C++
|
2008-11-15 00:09:21 +08:00
|
|
|
void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
|
|
|
|
const char *OpStrings[NUM_OVERLOADED_OPERATORS] = {
|
|
|
|
"",
|
|
|
|
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
|
|
|
|
Spelling,
|
|
|
|
#include "clang/Basic/OperatorKinds.def"
|
|
|
|
};
|
|
|
|
|
|
|
|
OverloadedOperatorKind Kind = Node->getOperator();
|
|
|
|
if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
|
|
|
|
if (Node->getNumArgs() == 1) {
|
|
|
|
OS << OpStrings[Kind] << ' ';
|
|
|
|
PrintExpr(Node->getArg(0));
|
|
|
|
} else {
|
|
|
|
PrintExpr(Node->getArg(0));
|
|
|
|
OS << ' ' << OpStrings[Kind];
|
|
|
|
}
|
2012-10-13 06:45:14 +08:00
|
|
|
} else if (Kind == OO_Arrow) {
|
|
|
|
PrintExpr(Node->getArg(0));
|
2008-11-15 00:09:21 +08:00
|
|
|
} else if (Kind == OO_Call) {
|
|
|
|
PrintExpr(Node->getArg(0));
|
|
|
|
OS << '(';
|
|
|
|
for (unsigned ArgIdx = 1; ArgIdx < Node->getNumArgs(); ++ArgIdx) {
|
|
|
|
if (ArgIdx > 1)
|
|
|
|
OS << ", ";
|
|
|
|
if (!isa<CXXDefaultArgExpr>(Node->getArg(ArgIdx)))
|
|
|
|
PrintExpr(Node->getArg(ArgIdx));
|
|
|
|
}
|
|
|
|
OS << ')';
|
|
|
|
} else if (Kind == OO_Subscript) {
|
|
|
|
PrintExpr(Node->getArg(0));
|
|
|
|
OS << '[';
|
|
|
|
PrintExpr(Node->getArg(1));
|
|
|
|
OS << ']';
|
|
|
|
} else if (Node->getNumArgs() == 1) {
|
|
|
|
OS << OpStrings[Kind] << ' ';
|
|
|
|
PrintExpr(Node->getArg(0));
|
|
|
|
} else if (Node->getNumArgs() == 2) {
|
|
|
|
PrintExpr(Node->getArg(0));
|
|
|
|
OS << ' ' << OpStrings[Kind] << ' ';
|
|
|
|
PrintExpr(Node->getArg(1));
|
|
|
|
} else {
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("unknown overloaded operator");
|
2008-11-15 00:09:21 +08:00
|
|
|
}
|
|
|
|
}
|
2007-05-28 14:56:27 +08:00
|
|
|
|
2008-12-22 13:46:06 +08:00
|
|
|
void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) {
|
2014-02-26 02:03:55 +08:00
|
|
|
// If we have a conversion operator call only print the argument.
|
|
|
|
CXXMethodDecl *MD = Node->getMethodDecl();
|
|
|
|
if (MD && isa<CXXConversionDecl>(MD)) {
|
|
|
|
PrintExpr(Node->getImplicitObjectArgument());
|
|
|
|
return;
|
|
|
|
}
|
2008-12-22 13:46:06 +08:00
|
|
|
VisitCallExpr(cast<CallExpr>(Node));
|
|
|
|
}
|
|
|
|
|
2011-02-10 05:07:24 +08:00
|
|
|
void StmtPrinter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *Node) {
|
|
|
|
PrintExpr(Node->getCallee());
|
|
|
|
OS << "<<<";
|
|
|
|
PrintCallArgs(Node->getConfig());
|
|
|
|
OS << ">>>(";
|
|
|
|
PrintCallArgs(Node);
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2008-10-28 03:41:14 +08:00
|
|
|
void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
|
|
|
|
OS << Node->getCastName() << '<';
|
2013-02-22 22:19:01 +08:00
|
|
|
Node->getTypeAsWritten().print(OS, Policy);
|
|
|
|
OS << ">(";
|
2007-05-28 14:56:27 +08:00
|
|
|
PrintExpr(Node->getSubExpr());
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2008-10-28 03:41:14 +08:00
|
|
|
void StmtPrinter::VisitCXXStaticCastExpr(CXXStaticCastExpr *Node) {
|
|
|
|
VisitCXXNamedCastExpr(Node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *Node) {
|
|
|
|
VisitCXXNamedCastExpr(Node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *Node) {
|
|
|
|
VisitCXXNamedCastExpr(Node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCXXConstCastExpr(CXXConstCastExpr *Node) {
|
|
|
|
VisitCXXNamedCastExpr(Node);
|
|
|
|
}
|
|
|
|
|
2008-11-11 19:37:55 +08:00
|
|
|
void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) {
|
|
|
|
OS << "typeid(";
|
|
|
|
if (Node->isTypeOperand()) {
|
2013-09-27 15:04:31 +08:00
|
|
|
Node->getTypeOperandSourceInfo()->getType().print(OS, Policy);
|
2008-11-11 19:37:55 +08:00
|
|
|
} else {
|
|
|
|
PrintExpr(Node->getExprOperand());
|
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2010-09-08 20:20:18 +08:00
|
|
|
void StmtPrinter::VisitCXXUuidofExpr(CXXUuidofExpr *Node) {
|
|
|
|
OS << "__uuidof(";
|
|
|
|
if (Node->isTypeOperand()) {
|
2013-09-27 15:04:31 +08:00
|
|
|
Node->getTypeOperandSourceInfo()->getType().print(OS, Policy);
|
2010-09-08 20:20:18 +08:00
|
|
|
} else {
|
|
|
|
PrintExpr(Node->getExprOperand());
|
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2013-04-16 15:28:30 +08:00
|
|
|
void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) {
|
|
|
|
PrintExpr(Node->getBaseExpr());
|
|
|
|
if (Node->isArrow())
|
|
|
|
OS << "->";
|
|
|
|
else
|
|
|
|
OS << ".";
|
|
|
|
if (NestedNameSpecifier *Qualifier =
|
|
|
|
Node->getQualifierLoc().getNestedNameSpecifier())
|
|
|
|
Qualifier->print(OS, Policy);
|
|
|
|
OS << Node->getPropertyDecl()->getDeclName();
|
|
|
|
}
|
|
|
|
|
2015-11-25 20:01:00 +08:00
|
|
|
void StmtPrinter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *Node) {
|
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << "[";
|
|
|
|
PrintExpr(Node->getIdx());
|
|
|
|
OS << "]";
|
|
|
|
}
|
|
|
|
|
2012-03-07 16:35:16 +08:00
|
|
|
void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
|
|
|
|
switch (Node->getLiteralOperatorKind()) {
|
|
|
|
case UserDefinedLiteral::LOK_Raw:
|
2012-03-09 18:10:02 +08:00
|
|
|
OS << cast<StringLiteral>(Node->getArg(0)->IgnoreImpCasts())->getString();
|
2012-03-07 16:35:16 +08:00
|
|
|
break;
|
|
|
|
case UserDefinedLiteral::LOK_Template: {
|
2018-04-11 06:54:42 +08:00
|
|
|
const auto *DRE = cast<DeclRefExpr>(Node->getCallee()->IgnoreImpCasts());
|
2012-03-09 18:10:02 +08:00
|
|
|
const TemplateArgumentList *Args =
|
|
|
|
cast<FunctionDecl>(DRE->getDecl())->getTemplateSpecializationArgs();
|
|
|
|
assert(Args);
|
2015-04-05 13:32:54 +08:00
|
|
|
|
|
|
|
if (Args->size() != 1) {
|
2015-10-08 08:17:59 +08:00
|
|
|
OS << "operator\"\"" << Node->getUDSuffix()->getName();
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, Args->asArray(), Policy);
|
2015-04-05 13:32:54 +08:00
|
|
|
OS << "()";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-09 18:10:02 +08:00
|
|
|
const TemplateArgument &Pack = Args->get(0);
|
2014-07-16 05:32:31 +08:00
|
|
|
for (const auto &P : Pack.pack_elements()) {
|
|
|
|
char C = (char)P.getAsIntegral().getZExtValue();
|
2012-03-07 16:35:16 +08:00
|
|
|
OS << C;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2012-03-08 17:02:38 +08:00
|
|
|
case UserDefinedLiteral::LOK_Integer: {
|
|
|
|
// Print integer literal without suffix.
|
2018-04-11 06:54:42 +08:00
|
|
|
const auto *Int = cast<IntegerLiteral>(Node->getCookedLiteral());
|
2012-03-08 17:02:38 +08:00
|
|
|
OS << Int->getValue().toString(10, /*isSigned*/false);
|
|
|
|
break;
|
|
|
|
}
|
2012-09-20 22:07:17 +08:00
|
|
|
case UserDefinedLiteral::LOK_Floating: {
|
|
|
|
// Print floating literal without suffix.
|
2018-04-11 06:54:42 +08:00
|
|
|
auto *Float = cast<FloatingLiteral>(Node->getCookedLiteral());
|
2012-09-20 22:07:17 +08:00
|
|
|
PrintFloatingLiteral(OS, Float, /*PrintSuffix=*/false);
|
|
|
|
break;
|
|
|
|
}
|
2012-03-07 16:35:16 +08:00
|
|
|
case UserDefinedLiteral::LOK_String:
|
|
|
|
case UserDefinedLiteral::LOK_Character:
|
|
|
|
PrintExpr(Node->getCookedLiteral());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
OS << Node->getUDSuffix()->getName();
|
|
|
|
}
|
|
|
|
|
2007-05-28 14:56:27 +08:00
|
|
|
void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
|
|
|
|
OS << (Node->getValue() ? "true" : "false");
|
|
|
|
}
|
|
|
|
|
2009-05-11 02:38:11 +08:00
|
|
|
void StmtPrinter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *Node) {
|
|
|
|
OS << "nullptr";
|
|
|
|
}
|
|
|
|
|
2008-11-04 22:32:21 +08:00
|
|
|
void StmtPrinter::VisitCXXThisExpr(CXXThisExpr *Node) {
|
|
|
|
OS << "this";
|
|
|
|
}
|
|
|
|
|
2008-02-26 08:51:44 +08:00
|
|
|
void StmtPrinter::VisitCXXThrowExpr(CXXThrowExpr *Node) {
|
2014-05-12 13:36:57 +08:00
|
|
|
if (!Node->getSubExpr())
|
2008-02-26 08:51:44 +08:00
|
|
|
OS << "throw";
|
|
|
|
else {
|
|
|
|
OS << "throw ";
|
|
|
|
PrintExpr(Node->getSubExpr());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-08 12:40:51 +08:00
|
|
|
void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) {
|
2013-04-21 06:23:05 +08:00
|
|
|
// Nothing to print: we picked up the default argument.
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Node) {
|
|
|
|
// Nothing to print: we picked up the default initializer.
|
2008-04-08 12:40:51 +08:00
|
|
|
}
|
|
|
|
|
2008-08-22 23:38:55 +08:00
|
|
|
void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
|
2013-02-22 22:19:01 +08:00
|
|
|
Node->getType().print(OS, Policy);
|
2015-01-29 06:06:01 +08:00
|
|
|
// If there are no parens, this is list-initialization, and the braces are
|
|
|
|
// part of the syntax of the inner construct.
|
|
|
|
if (Node->getLParenLoc().isValid())
|
|
|
|
OS << "(";
|
2008-08-22 23:38:55 +08:00
|
|
|
PrintExpr(Node->getSubExpr());
|
2015-01-29 06:06:01 +08:00
|
|
|
if (Node->getLParenLoc().isValid())
|
|
|
|
OS << ")";
|
2008-08-22 23:38:55 +08:00
|
|
|
}
|
|
|
|
|
2009-05-31 04:03:25 +08:00
|
|
|
void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
|
2010-01-29 10:39:32 +08:00
|
|
|
PrintExpr(Node->getSubExpr());
|
|
|
|
}
|
|
|
|
|
2009-01-17 02:33:17 +08:00
|
|
|
void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
|
2013-02-22 22:19:01 +08:00
|
|
|
Node->getType().print(OS, Policy);
|
2015-02-05 15:02:11 +08:00
|
|
|
if (Node->isStdInitListInitialization())
|
|
|
|
/* Nothing to do; braces are part of creating the std::initializer_list. */;
|
|
|
|
else if (Node->isListInitialization())
|
2015-01-29 06:06:01 +08:00
|
|
|
OS << "{";
|
|
|
|
else
|
|
|
|
OS << "(";
|
2009-01-17 02:33:17 +08:00
|
|
|
for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(),
|
2009-09-09 23:08:12 +08:00
|
|
|
ArgEnd = Node->arg_end();
|
2009-01-17 02:33:17 +08:00
|
|
|
Arg != ArgEnd; ++Arg) {
|
2015-07-18 22:35:53 +08:00
|
|
|
if ((*Arg)->isDefaultArgument())
|
2013-05-25 00:11:44 +08:00
|
|
|
break;
|
2009-01-17 02:33:17 +08:00
|
|
|
if (Arg != Node->arg_begin())
|
|
|
|
OS << ", ";
|
|
|
|
PrintExpr(*Arg);
|
|
|
|
}
|
2015-02-05 15:02:11 +08:00
|
|
|
if (Node->isStdInitListInitialization())
|
|
|
|
/* See above. */;
|
|
|
|
else if (Node->isListInitialization())
|
2015-01-29 06:06:01 +08:00
|
|
|
OS << "}";
|
|
|
|
else
|
|
|
|
OS << ")";
|
2009-01-17 02:33:17 +08:00
|
|
|
}
|
|
|
|
|
2012-02-07 18:09:13 +08:00
|
|
|
void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
|
|
|
|
OS << '[';
|
|
|
|
bool NeedComma = false;
|
|
|
|
switch (Node->getCaptureDefault()) {
|
|
|
|
case LCD_None:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LCD_ByCopy:
|
|
|
|
OS << '=';
|
|
|
|
NeedComma = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LCD_ByRef:
|
|
|
|
OS << '&';
|
|
|
|
NeedComma = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
for (LambdaExpr::capture_iterator C = Node->explicit_capture_begin(),
|
|
|
|
CEnd = Node->explicit_capture_end();
|
|
|
|
C != CEnd;
|
|
|
|
++C) {
|
2017-11-11 08:54:25 +08:00
|
|
|
if (C->capturesVLAType())
|
|
|
|
continue;
|
|
|
|
|
2012-02-07 18:09:13 +08:00
|
|
|
if (NeedComma)
|
|
|
|
OS << ", ";
|
|
|
|
NeedComma = true;
|
|
|
|
|
|
|
|
switch (C->getCaptureKind()) {
|
|
|
|
case LCK_This:
|
|
|
|
OS << "this";
|
|
|
|
break;
|
2018-04-11 06:54:42 +08:00
|
|
|
|
[Cxx1z] Implement Lambda Capture of *this by Value as [=,*this] (P0018R3)
Implement lambda capture of *this by copy.
For e.g.:
struct A {
int d = 10;
auto foo() { return [*this] (auto a) mutable { d+=a; return d; }; }
};
auto L = A{}.foo(); // A{}'s lifetime is gone.
// Below is still ok, because *this was captured by value.
assert(L(10) == 20);
assert(L(100) == 120);
If the capture was implicit, or [this] (i.e. *this was captured by reference), this code would be otherwise undefined.
Implementation Strategy:
- amend the parser to accept *this in the lambda introducer
- add a new king of capture LCK_StarThis
- teach Sema::CheckCXXThisCapture to handle by copy captures of the
enclosing object (i.e. *this)
- when CheckCXXThisCapture does capture by copy, the corresponding
initializer expression for the closure's data member
direct-initializes it thus making a copy of '*this'.
- in codegen, when assigning to CXXThisValue, if *this was captured by
copy, make sure it points to the corresponding field member, and
not, unlike when captured by reference, what the field member points
to.
- mark feature as implemented in svn
Much gratitude to Richard Smith for his carefully illuminating reviews!
llvm-svn: 263921
2016-03-21 17:25:37 +08:00
|
|
|
case LCK_StarThis:
|
|
|
|
OS << "*this";
|
|
|
|
break;
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2012-02-07 18:09:13 +08:00
|
|
|
case LCK_ByRef:
|
2015-05-08 02:48:18 +08:00
|
|
|
if (Node->getCaptureDefault() != LCD_ByRef || Node->isInitCapture(C))
|
2012-02-07 18:09:13 +08:00
|
|
|
OS << '&';
|
|
|
|
OS << C->getCapturedVar()->getName();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LCK_ByCopy:
|
|
|
|
OS << C->getCapturedVar()->getName();
|
|
|
|
break;
|
2018-04-11 06:54:42 +08:00
|
|
|
|
2014-08-28 12:28:19 +08:00
|
|
|
case LCK_VLAType:
|
|
|
|
llvm_unreachable("VLA type in explicit captures.");
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
2013-09-28 12:02:39 +08:00
|
|
|
|
2015-05-08 02:48:18 +08:00
|
|
|
if (Node->isInitCapture(C))
|
2013-09-28 12:02:39 +08:00
|
|
|
PrintExpr(C->getCapturedVar()->getInit());
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
|
|
|
OS << ']';
|
|
|
|
|
2019-05-04 18:49:46 +08:00
|
|
|
if (!Node->getExplicitTemplateParameters().empty()) {
|
|
|
|
Node->getTemplateParameterList()->print(
|
|
|
|
OS, Node->getLambdaClass()->getASTContext(),
|
|
|
|
/*OmitTemplateKW*/true);
|
|
|
|
}
|
|
|
|
|
2012-02-07 18:09:13 +08:00
|
|
|
if (Node->hasExplicitParameters()) {
|
2019-05-04 18:49:46 +08:00
|
|
|
OS << '(';
|
2012-02-07 18:09:13 +08:00
|
|
|
CXXMethodDecl *Method = Node->getCallOperator();
|
|
|
|
NeedComma = false;
|
2018-04-11 06:54:42 +08:00
|
|
|
for (const auto *P : Method->parameters()) {
|
2012-02-07 18:09:13 +08:00
|
|
|
if (NeedComma) {
|
|
|
|
OS << ", ";
|
|
|
|
} else {
|
|
|
|
NeedComma = true;
|
|
|
|
}
|
2014-03-08 01:50:17 +08:00
|
|
|
std::string ParamStr = P->getNameAsString();
|
|
|
|
P->getOriginalType().print(OS, Policy, ParamStr);
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
|
|
|
if (Method->isVariadic()) {
|
|
|
|
if (NeedComma)
|
|
|
|
OS << ", ";
|
|
|
|
OS << "...";
|
|
|
|
}
|
|
|
|
OS << ')';
|
|
|
|
|
|
|
|
if (Node->isMutable())
|
|
|
|
OS << " mutable";
|
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
auto *Proto = Method->getType()->getAs<FunctionProtoType>();
|
2013-02-22 23:46:01 +08:00
|
|
|
Proto->printExceptionSpecification(OS, Policy);
|
2012-02-07 18:09:13 +08:00
|
|
|
|
2012-12-21 03:22:21 +08:00
|
|
|
// FIXME: Attributes
|
2012-02-07 18:09:13 +08:00
|
|
|
|
2012-02-14 06:00:16 +08:00
|
|
|
// Print the trailing return type if it was specified in the source.
|
2013-02-22 22:19:01 +08:00
|
|
|
if (Node->hasExplicitResultType()) {
|
|
|
|
OS << " -> ";
|
2014-01-26 00:55:45 +08:00
|
|
|
Proto->getReturnType().print(OS, Policy);
|
2013-02-22 22:19:01 +08:00
|
|
|
}
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Print the body.
|
|
|
|
OS << ' ';
|
2019-05-04 18:49:46 +08:00
|
|
|
PrintRawCompoundStmt(Node->getBody());
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
|
|
|
|
2010-07-08 14:14:04 +08:00
|
|
|
void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) {
|
2010-09-08 08:15:04 +08:00
|
|
|
if (TypeSourceInfo *TSInfo = Node->getTypeSourceInfo())
|
2013-02-22 22:19:01 +08:00
|
|
|
TSInfo->getType().print(OS, Policy);
|
2010-09-08 08:15:04 +08:00
|
|
|
else
|
2013-02-22 22:19:01 +08:00
|
|
|
Node->getType().print(OS, Policy);
|
|
|
|
OS << "()";
|
2008-08-22 23:38:55 +08:00
|
|
|
}
|
|
|
|
|
2008-11-22 03:14:01 +08:00
|
|
|
void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
|
|
|
|
if (E->isGlobalNew())
|
|
|
|
OS << "::";
|
|
|
|
OS << "new ";
|
|
|
|
unsigned NumPlace = E->getNumPlacementArgs();
|
2012-10-19 04:54:37 +08:00
|
|
|
if (NumPlace > 0 && !isa<CXXDefaultArgExpr>(E->getPlacementArg(0))) {
|
2008-11-22 03:14:01 +08:00
|
|
|
OS << "(";
|
|
|
|
PrintExpr(E->getPlacementArg(0));
|
|
|
|
for (unsigned i = 1; i < NumPlace; ++i) {
|
2012-10-19 04:54:37 +08:00
|
|
|
if (isa<CXXDefaultArgExpr>(E->getPlacementArg(i)))
|
|
|
|
break;
|
2008-11-22 03:14:01 +08:00
|
|
|
OS << ", ";
|
|
|
|
PrintExpr(E->getPlacementArg(i));
|
|
|
|
}
|
|
|
|
OS << ") ";
|
|
|
|
}
|
|
|
|
if (E->isParenTypeId())
|
|
|
|
OS << "(";
|
2008-12-03 06:08:59 +08:00
|
|
|
std::string TypeS;
|
|
|
|
if (Expr *Size = E->getArraySize()) {
|
|
|
|
llvm::raw_string_ostream s(TypeS);
|
2013-02-22 22:19:01 +08:00
|
|
|
s << '[';
|
2012-08-16 11:56:14 +08:00
|
|
|
Size->printPretty(s, Helper, Policy);
|
2013-02-22 22:19:01 +08:00
|
|
|
s << ']';
|
2008-12-03 06:08:59 +08:00
|
|
|
}
|
2013-02-22 22:19:01 +08:00
|
|
|
E->getAllocatedType().print(OS, Policy, TypeS);
|
2008-11-22 03:14:01 +08:00
|
|
|
if (E->isParenTypeId())
|
|
|
|
OS << ")";
|
|
|
|
|
2012-02-16 20:22:20 +08:00
|
|
|
CXXNewExpr::InitializationStyle InitStyle = E->getInitializationStyle();
|
|
|
|
if (InitStyle) {
|
|
|
|
if (InitStyle == CXXNewExpr::CallInit)
|
|
|
|
OS << "(";
|
|
|
|
PrintExpr(E->getInitializer());
|
|
|
|
if (InitStyle == CXXNewExpr::CallInit)
|
|
|
|
OS << ")";
|
2008-11-22 03:14:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
|
|
|
|
if (E->isGlobalDelete())
|
|
|
|
OS << "::";
|
|
|
|
OS << "delete ";
|
|
|
|
if (E->isArrayForm())
|
|
|
|
OS << "[] ";
|
|
|
|
PrintExpr(E->getArgument());
|
|
|
|
}
|
|
|
|
|
2009-09-05 01:36:40 +08:00
|
|
|
void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
|
|
|
|
PrintExpr(E->getBase());
|
|
|
|
if (E->isArrow())
|
|
|
|
OS << "->";
|
|
|
|
else
|
|
|
|
OS << '.';
|
|
|
|
if (E->getQualifier())
|
|
|
|
E->getQualifier()->print(OS, Policy);
|
2012-10-24 04:26:57 +08:00
|
|
|
OS << "~";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-25 09:56:36 +08:00
|
|
|
if (IdentifierInfo *II = E->getDestroyedTypeIdentifier())
|
|
|
|
OS << II->getName();
|
|
|
|
else
|
2013-02-22 22:19:01 +08:00
|
|
|
E->getDestroyedType().print(OS, Policy);
|
2009-09-05 01:36:40 +08:00
|
|
|
}
|
|
|
|
|
2009-04-23 10:32:43 +08:00
|
|
|
void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
|
2015-02-05 15:02:11 +08:00
|
|
|
if (E->isListInitialization() && !E->isStdInitListInitialization())
|
2015-01-30 10:04:26 +08:00
|
|
|
OS << "{";
|
2012-12-19 09:39:02 +08:00
|
|
|
|
2011-01-25 01:25:03 +08:00
|
|
|
for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
|
|
|
|
if (isa<CXXDefaultArgExpr>(E->getArg(i))) {
|
|
|
|
// Don't print any defaulted arguments
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i) OS << ", ";
|
|
|
|
PrintExpr(E->getArg(i));
|
2010-01-14 05:41:11 +08:00
|
|
|
}
|
2012-12-19 09:39:02 +08:00
|
|
|
|
2015-02-05 15:02:11 +08:00
|
|
|
if (E->isListInitialization() && !E->isStdInitListInitialization())
|
2015-01-30 10:04:26 +08:00
|
|
|
OS << "}";
|
2009-04-23 10:32:43 +08:00
|
|
|
}
|
|
|
|
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
void StmtPrinter::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E) {
|
|
|
|
// Parens are printed by the surrounding context.
|
|
|
|
OS << "<forwarded>";
|
|
|
|
}
|
|
|
|
|
2013-06-13 06:31:48 +08:00
|
|
|
void StmtPrinter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
|
|
|
|
PrintExpr(E->getSubExpr());
|
|
|
|
}
|
|
|
|
|
2010-12-06 16:20:24 +08:00
|
|
|
void StmtPrinter::VisitExprWithCleanups(ExprWithCleanups *E) {
|
2013-12-07 01:56:43 +08:00
|
|
|
// Just forward to the subexpression.
|
2009-04-25 06:47:04 +08:00
|
|
|
PrintExpr(E->getSubExpr());
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void
|
Introduce a new expression type, CXXUnresolvedConstructExpr, to
describe the construction of a value of a given type using function
syntax, e.g.,
T(a1, a2, ..., aN)
when the type or any of its arguments are type-dependent. In this
case, we don't know what kind of type-construction this will be: it
might construct a temporary of type 'T' (which might be a class or
non-class type) or might perform a conversion to type 'T'. Also,
implement printing of and template instantiation for this new
expression type. Due to the change in Sema::ActOnCXXTypeConstructExpr,
our existing tests cover template instantiation of this new expression
node.
llvm-svn: 72176
2009-05-21 02:46:25 +08:00
|
|
|
StmtPrinter::VisitCXXUnresolvedConstructExpr(
|
|
|
|
CXXUnresolvedConstructExpr *Node) {
|
2013-02-22 22:19:01 +08:00
|
|
|
Node->getTypeAsWritten().print(OS, Policy);
|
Introduce a new expression type, CXXUnresolvedConstructExpr, to
describe the construction of a value of a given type using function
syntax, e.g.,
T(a1, a2, ..., aN)
when the type or any of its arguments are type-dependent. In this
case, we don't know what kind of type-construction this will be: it
might construct a temporary of type 'T' (which might be a class or
non-class type) or might perform a conversion to type 'T'. Also,
implement printing of and template instantiation for this new
expression type. Due to the change in Sema::ActOnCXXTypeConstructExpr,
our existing tests cover template instantiation of this new expression
node.
llvm-svn: 72176
2009-05-21 02:46:25 +08:00
|
|
|
OS << "(";
|
|
|
|
for (CXXUnresolvedConstructExpr::arg_iterator Arg = Node->arg_begin(),
|
2009-09-09 23:08:12 +08:00
|
|
|
ArgEnd = Node->arg_end();
|
Introduce a new expression type, CXXUnresolvedConstructExpr, to
describe the construction of a value of a given type using function
syntax, e.g.,
T(a1, a2, ..., aN)
when the type or any of its arguments are type-dependent. In this
case, we don't know what kind of type-construction this will be: it
might construct a temporary of type 'T' (which might be a class or
non-class type) or might perform a conversion to type 'T'. Also,
implement printing of and template instantiation for this new
expression type. Due to the change in Sema::ActOnCXXTypeConstructExpr,
our existing tests cover template instantiation of this new expression
node.
llvm-svn: 72176
2009-05-21 02:46:25 +08:00
|
|
|
Arg != ArgEnd; ++Arg) {
|
|
|
|
if (Arg != Node->arg_begin())
|
|
|
|
OS << ", ";
|
|
|
|
PrintExpr(*Arg);
|
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2009-11-20 06:55:06 +08:00
|
|
|
void StmtPrinter::VisitCXXDependentScopeMemberExpr(
|
|
|
|
CXXDependentScopeMemberExpr *Node) {
|
2009-12-02 06:10:20 +08:00
|
|
|
if (!Node->isImplicitAccess()) {
|
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << (Node->isArrow() ? "->" : ".");
|
|
|
|
}
|
2009-09-04 00:14:30 +08:00
|
|
|
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
|
|
|
|
Qualifier->print(OS, Policy);
|
2012-01-27 17:46:47 +08:00
|
|
|
if (Node->hasTemplateKeyword())
|
2009-09-09 08:23:06 +08:00
|
|
|
OS << "template ";
|
2010-08-12 06:01:17 +08:00
|
|
|
OS << Node->getMemberNameInfo();
|
2013-02-22 23:46:01 +08:00
|
|
|
if (Node->hasExplicitTemplateArgs())
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, Node->template_arguments(), Policy);
|
2009-05-23 05:13:27 +08:00
|
|
|
}
|
|
|
|
|
2009-12-01 06:42:35 +08:00
|
|
|
void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
|
2009-12-02 06:10:20 +08:00
|
|
|
if (!Node->isImplicitAccess()) {
|
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << (Node->isArrow() ? "->" : ".");
|
|
|
|
}
|
2009-12-01 06:42:35 +08:00
|
|
|
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
|
|
|
|
Qualifier->print(OS, Policy);
|
2012-01-27 17:46:47 +08:00
|
|
|
if (Node->hasTemplateKeyword())
|
|
|
|
OS << "template ";
|
2010-08-12 06:01:17 +08:00
|
|
|
OS << Node->getMemberNameInfo();
|
2013-02-22 23:46:01 +08:00
|
|
|
if (Node->hasExplicitTemplateArgs())
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, Node->template_arguments(), Policy);
|
2009-12-01 06:42:35 +08:00
|
|
|
}
|
|
|
|
|
2012-02-24 15:38:34 +08:00
|
|
|
static const char *getTypeTraitName(TypeTrait TT) {
|
|
|
|
switch (TT) {
|
2014-01-01 13:57:51 +08:00
|
|
|
#define TYPE_TRAIT_1(Spelling, Name, Key) \
|
|
|
|
case clang::UTT_##Name: return #Spelling;
|
2013-12-14 04:49:58 +08:00
|
|
|
#define TYPE_TRAIT_2(Spelling, Name, Key) \
|
|
|
|
case clang::BTT_##Name: return #Spelling;
|
2013-12-13 05:23:03 +08:00
|
|
|
#define TYPE_TRAIT_N(Spelling, Name, Key) \
|
|
|
|
case clang::TT_##Name: return #Spelling;
|
|
|
|
#include "clang/Basic/TokenKinds.def"
|
2012-02-24 15:38:34 +08:00
|
|
|
}
|
|
|
|
llvm_unreachable("Type trait not covered by switch");
|
|
|
|
}
|
|
|
|
|
2011-04-28 08:16:57 +08:00
|
|
|
static const char *getTypeTraitName(ArrayTypeTrait ATT) {
|
|
|
|
switch (ATT) {
|
|
|
|
case ATT_ArrayRank: return "__array_rank";
|
|
|
|
case ATT_ArrayExtent: return "__array_extent";
|
|
|
|
}
|
2011-05-01 15:23:23 +08:00
|
|
|
llvm_unreachable("Array type trait not covered by switch");
|
2011-04-28 08:16:57 +08:00
|
|
|
}
|
|
|
|
|
2011-04-25 14:54:41 +08:00
|
|
|
static const char *getExpressionTraitName(ExpressionTrait ET) {
|
|
|
|
switch (ET) {
|
|
|
|
case ET_IsLValueExpr: return "__is_lvalue_expr";
|
|
|
|
case ET_IsRValueExpr: return "__is_rvalue_expr";
|
|
|
|
}
|
2011-05-01 15:23:23 +08:00
|
|
|
llvm_unreachable("Expression type trait not covered by switch");
|
2011-04-25 14:54:41 +08:00
|
|
|
}
|
|
|
|
|
2012-02-24 15:38:34 +08:00
|
|
|
void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) {
|
|
|
|
OS << getTypeTraitName(E->getTrait()) << "(";
|
|
|
|
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
|
|
|
|
if (I > 0)
|
|
|
|
OS << ", ";
|
2013-02-22 22:19:01 +08:00
|
|
|
E->getArg(I)->getType().print(OS, Policy);
|
2012-02-24 15:38:34 +08:00
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2011-04-28 08:16:57 +08:00
|
|
|
void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
|
2013-02-22 22:19:01 +08:00
|
|
|
OS << getTypeTraitName(E->getTrait()) << '(';
|
|
|
|
E->getQueriedType().print(OS, Policy);
|
|
|
|
OS << ')';
|
2011-04-28 08:16:57 +08:00
|
|
|
}
|
|
|
|
|
2011-04-25 14:54:41 +08:00
|
|
|
void StmtPrinter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
|
2013-02-22 22:19:01 +08:00
|
|
|
OS << getExpressionTraitName(E->getTrait()) << '(';
|
|
|
|
PrintExpr(E->getQueriedExpression());
|
|
|
|
OS << ')';
|
2011-04-25 14:54:41 +08:00
|
|
|
}
|
|
|
|
|
2010-09-11 04:55:43 +08:00
|
|
|
void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
|
|
|
|
OS << "noexcept(";
|
|
|
|
PrintExpr(E->getOperand());
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2011-01-05 01:33:58 +08:00
|
|
|
void StmtPrinter::VisitPackExpansionExpr(PackExpansionExpr *E) {
|
2011-01-04 01:17:50 +08:00
|
|
|
PrintExpr(E->getPattern());
|
|
|
|
OS << "...";
|
|
|
|
}
|
|
|
|
|
2011-01-05 01:33:58 +08:00
|
|
|
void StmtPrinter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
|
2012-02-07 19:57:57 +08:00
|
|
|
OS << "sizeof...(" << *E->getPack() << ")";
|
2011-01-05 01:33:58 +08:00
|
|
|
}
|
|
|
|
|
2011-01-15 09:15:58 +08:00
|
|
|
void StmtPrinter::VisitSubstNonTypeTemplateParmPackExpr(
|
|
|
|
SubstNonTypeTemplateParmPackExpr *Node) {
|
2012-02-07 19:57:57 +08:00
|
|
|
OS << *Node->getParameterPack();
|
2011-01-15 09:15:58 +08:00
|
|
|
}
|
|
|
|
|
2011-07-15 13:09:51 +08:00
|
|
|
void StmtPrinter::VisitSubstNonTypeTemplateParmExpr(
|
|
|
|
SubstNonTypeTemplateParmExpr *Node) {
|
|
|
|
Visit(Node->getReplacement());
|
|
|
|
}
|
|
|
|
|
2012-09-12 08:56:43 +08:00
|
|
|
void StmtPrinter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
|
|
|
|
OS << *E->getParameterPack();
|
|
|
|
}
|
|
|
|
|
2011-06-22 01:03:29 +08:00
|
|
|
void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
|
|
|
|
PrintExpr(Node->GetTemporaryExpr());
|
|
|
|
}
|
|
|
|
|
2014-11-08 13:07:16 +08:00
|
|
|
void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) {
|
|
|
|
OS << "(";
|
|
|
|
if (E->getLHS()) {
|
|
|
|
PrintExpr(E->getLHS());
|
|
|
|
OS << " " << BinaryOperator::getOpcodeStr(E->getOperator()) << " ";
|
|
|
|
}
|
|
|
|
OS << "...";
|
|
|
|
if (E->getRHS()) {
|
|
|
|
OS << " " << BinaryOperator::getOpcodeStr(E->getOperator()) << " ";
|
|
|
|
PrintExpr(E->getRHS());
|
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2015-10-27 14:02:45 +08:00
|
|
|
// C++ Coroutines TS
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
|
|
|
|
Visit(S->getBody());
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCoreturnStmt(CoreturnStmt *S) {
|
|
|
|
OS << "co_return";
|
|
|
|
if (S->getOperand()) {
|
|
|
|
OS << " ";
|
|
|
|
Visit(S->getOperand());
|
|
|
|
}
|
|
|
|
OS << ";";
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitCoawaitExpr(CoawaitExpr *S) {
|
|
|
|
OS << "co_await ";
|
|
|
|
PrintExpr(S->getOperand());
|
|
|
|
}
|
|
|
|
|
2017-03-07 07:38:15 +08:00
|
|
|
void StmtPrinter::VisitDependentCoawaitExpr(DependentCoawaitExpr *S) {
|
|
|
|
OS << "co_await ";
|
|
|
|
PrintExpr(S->getOperand());
|
|
|
|
}
|
|
|
|
|
2015-10-27 14:02:45 +08:00
|
|
|
void StmtPrinter::VisitCoyieldExpr(CoyieldExpr *S) {
|
|
|
|
OS << "co_yield ";
|
|
|
|
PrintExpr(S->getOperand());
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// Obj-C
|
2007-08-22 01:43:55 +08:00
|
|
|
|
|
|
|
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
|
|
|
|
OS << "@";
|
|
|
|
VisitStringLiteral(Node->getString());
|
|
|
|
}
|
2007-05-28 14:56:27 +08:00
|
|
|
|
2012-04-19 08:25:12 +08:00
|
|
|
void StmtPrinter::VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
|
2012-03-07 04:05:56 +08:00
|
|
|
OS << "@";
|
2012-04-19 08:25:12 +08:00
|
|
|
Visit(E->getSubExpr());
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
|
|
|
|
OS << "@[ ";
|
2015-07-19 01:09:36 +08:00
|
|
|
ObjCArrayLiteral::child_range Ch = E->children();
|
|
|
|
for (auto I = Ch.begin(), E = Ch.end(); I != E; ++I) {
|
|
|
|
if (I != Ch.begin())
|
2012-03-07 04:05:56 +08:00
|
|
|
OS << ", ";
|
2015-07-19 01:09:36 +08:00
|
|
|
Visit(*I);
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
|
|
|
OS << " ]";
|
|
|
|
}
|
|
|
|
|
|
|
|
void StmtPrinter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
|
|
|
|
OS << "@{ ";
|
|
|
|
for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
|
|
|
|
if (I > 0)
|
|
|
|
OS << ", ";
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
ObjCDictionaryElement Element = E->getKeyValueElement(I);
|
|
|
|
Visit(Element.Key);
|
|
|
|
OS << " : ";
|
|
|
|
Visit(Element.Value);
|
|
|
|
if (Element.isPackExpansion())
|
|
|
|
OS << "...";
|
|
|
|
}
|
|
|
|
OS << " }";
|
|
|
|
}
|
|
|
|
|
2007-08-22 23:14:15 +08:00
|
|
|
void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
|
2013-02-22 22:19:01 +08:00
|
|
|
OS << "@encode(";
|
|
|
|
Node->getEncodedType().print(OS, Policy);
|
|
|
|
OS << ')';
|
2007-08-22 23:14:15 +08:00
|
|
|
}
|
|
|
|
|
2007-10-17 04:40:23 +08:00
|
|
|
void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
|
2014-01-04 01:59:55 +08:00
|
|
|
OS << "@selector(";
|
|
|
|
Node->getSelector().print(OS);
|
|
|
|
OS << ')';
|
2007-10-17 04:40:23 +08:00
|
|
|
}
|
|
|
|
|
2007-10-18 00:58:11 +08:00
|
|
|
void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
|
2011-10-15 02:45:37 +08:00
|
|
|
OS << "@protocol(" << *Node->getProtocol() << ')';
|
2007-10-18 00:58:11 +08:00
|
|
|
}
|
|
|
|
|
2007-09-19 07:55:05 +08:00
|
|
|
void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
|
|
|
|
OS << "[";
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
switch (Mess->getReceiverKind()) {
|
|
|
|
case ObjCMessageExpr::Instance:
|
|
|
|
PrintExpr(Mess->getInstanceReceiver());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCMessageExpr::Class:
|
2013-02-22 22:19:01 +08:00
|
|
|
Mess->getClassReceiver().print(OS, Policy);
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCMessageExpr::SuperInstance:
|
|
|
|
case ObjCMessageExpr::SuperClass:
|
|
|
|
OS << "Super";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-05-03 01:32:38 +08:00
|
|
|
OS << ' ';
|
2008-04-16 12:30:16 +08:00
|
|
|
Selector selector = Mess->getSelector();
|
2007-10-03 04:01:56 +08:00
|
|
|
if (selector.isUnarySelector()) {
|
2011-02-19 06:29:55 +08:00
|
|
|
OS << selector.getNameForSlot(0);
|
2007-10-03 04:01:56 +08:00
|
|
|
} else {
|
|
|
|
for (unsigned i = 0, e = Mess->getNumArgs(); i != e; ++i) {
|
2008-05-03 01:32:38 +08:00
|
|
|
if (i < selector.getNumArgs()) {
|
|
|
|
if (i > 0) OS << ' ';
|
|
|
|
if (selector.getIdentifierInfoForSlot(i))
|
2008-11-24 12:00:27 +08:00
|
|
|
OS << selector.getIdentifierInfoForSlot(i)->getName() << ':';
|
2008-05-03 01:32:38 +08:00
|
|
|
else
|
|
|
|
OS << ":";
|
|
|
|
}
|
|
|
|
else OS << ", "; // Handle variadic methods.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-03 04:01:56 +08:00
|
|
|
PrintExpr(Mess->getArg(i));
|
|
|
|
}
|
2007-09-19 07:55:05 +08:00
|
|
|
}
|
|
|
|
OS << "]";
|
|
|
|
}
|
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
void StmtPrinter::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) {
|
|
|
|
OS << (Node->getValue() ? "__objc_yes" : "__objc_no");
|
|
|
|
}
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
void
|
|
|
|
StmtPrinter::VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) {
|
|
|
|
PrintExpr(E->getSubExpr());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
StmtPrinter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) {
|
2013-02-22 22:19:01 +08:00
|
|
|
OS << '(' << E->getBridgeKindName();
|
|
|
|
E->getType().print(OS, Policy);
|
|
|
|
OS << ')';
|
2011-06-16 07:02:42 +08:00
|
|
|
PrintExpr(E->getSubExpr());
|
|
|
|
}
|
2008-11-04 22:56:14 +08:00
|
|
|
|
2008-09-04 02:15:37 +08:00
|
|
|
void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
|
2008-10-09 01:01:13 +08:00
|
|
|
BlockDecl *BD = Node->getBlockDecl();
|
2008-09-04 02:15:37 +08:00
|
|
|
OS << "^";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-09-04 02:15:37 +08:00
|
|
|
const FunctionType *AFT = Node->getFunctionType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 07:50:07 +08:00
|
|
|
if (isa<FunctionNoProtoType>(AFT)) {
|
2008-09-04 02:15:37 +08:00
|
|
|
OS << "()";
|
2009-02-27 07:50:07 +08:00
|
|
|
} else if (!BD->param_empty() || cast<FunctionProtoType>(AFT)->isVariadic()) {
|
2008-09-04 02:15:37 +08:00
|
|
|
OS << '(';
|
2008-10-09 01:01:13 +08:00
|
|
|
for (BlockDecl::param_iterator AI = BD->param_begin(),
|
|
|
|
E = BD->param_end(); AI != E; ++AI) {
|
|
|
|
if (AI != BD->param_begin()) OS << ", ";
|
2013-02-22 22:19:01 +08:00
|
|
|
std::string ParamStr = (*AI)->getNameAsString();
|
|
|
|
(*AI)->getType().print(OS, Policy, ParamStr);
|
2008-09-04 02:15:37 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
const auto *FT = cast<FunctionProtoType>(AFT);
|
2008-09-04 02:15:37 +08:00
|
|
|
if (FT->isVariadic()) {
|
2008-10-09 01:01:13 +08:00
|
|
|
if (!BD->param_empty()) OS << ", ";
|
2008-09-04 02:15:37 +08:00
|
|
|
OS << "...";
|
|
|
|
}
|
|
|
|
OS << ')';
|
|
|
|
}
|
2012-12-05 05:15:23 +08:00
|
|
|
OS << "{ }";
|
2008-09-04 02:15:37 +08:00
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
|
2011-12-01 06:08:08 +08:00
|
|
|
PrintExpr(Node->getSourceExpr());
|
|
|
|
}
|
2010-11-16 07:31:06 +08:00
|
|
|
|
2014-10-28 02:07:20 +08:00
|
|
|
void StmtPrinter::VisitTypoExpr(TypoExpr *Node) {
|
|
|
|
// TODO: Print something reasonable for a TypoExpr, if necessary.
|
2016-01-30 16:03:54 +08:00
|
|
|
llvm_unreachable("Cannot print TypoExpr nodes");
|
2014-10-28 02:07:20 +08:00
|
|
|
}
|
|
|
|
|
2011-06-04 08:47:47 +08:00
|
|
|
void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) {
|
|
|
|
OS << "__builtin_astype(";
|
|
|
|
PrintExpr(Node->getSrcExpr());
|
2013-02-22 22:19:01 +08:00
|
|
|
OS << ", ";
|
|
|
|
Node->getType().print(OS, Policy);
|
2011-06-04 08:47:47 +08:00
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2006-11-04 15:16:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Stmt method implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-08-22 14:02:26 +08:00
|
|
|
void Stmt::dumpPretty(const ASTContext &Context) const {
|
2014-05-12 13:36:57 +08:00
|
|
|
printPretty(llvm::errs(), nullptr, PrintingPolicy(Context.getLangOpts()));
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
|
|
|
|
2017-08-17 21:41:55 +08:00
|
|
|
void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper,
|
|
|
|
const PrintingPolicy &Policy, unsigned Indentation,
|
2018-09-15 10:02:31 +08:00
|
|
|
StringRef NL,
|
2017-08-17 21:41:55 +08:00
|
|
|
const ASTContext *Context) const {
|
2018-09-15 10:02:31 +08:00
|
|
|
StmtPrinter P(OS, Helper, Policy, Indentation, NL, Context);
|
2007-08-21 12:04:25 +08:00
|
|
|
P.Visit(const_cast<Stmt*>(this));
|
2006-11-04 15:16:25 +08:00
|
|
|
}
|
2007-09-01 05:30:12 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// PrinterHelper
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
// Implement virtual destructor.
|
2018-04-11 06:54:42 +08:00
|
|
|
PrinterHelper::~PrinterHelper() = default;
|