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"
|
[analyzer][AST] print() JSONify: Stmt implementation
Summary:
This patch also adds a function called `JsonFormat()` which:
- Flattens the string so removes the new-lines.
- Escapes double quotes.
Reviewers: NoQ, xazax.hun, ravikandhadai, baloghadamsoftware, Szelethus
Reviewed By: NoQ
Subscribers: cfe-commits, szepet, rnkovacs, a.sidorin, mikhail.ramalho,
donat.nagy, dkrupp
Tags: #clang
Differential Revision: https://reviews.llvm.org/D62494
llvm-svn: 362000
2019-05-30 02:17:18 +08:00
|
|
|
#include "clang/Basic/JsonSupport.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#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"
|
2021-06-11 20:19:00 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2018-04-11 06:54:42 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#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,
|
2020-01-29 03:23:46 +08:00
|
|
|
StringRef NL = "\n", const ASTContext *Context = nullptr)
|
2017-08-17 21:41:55 +08:00
|
|
|
: 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
|
|
|
|
2020-01-29 03:23:46 +08:00
|
|
|
void PrintStmt(Stmt *S) { PrintStmt(S, Policy.Indentation); }
|
2009-05-30 04:38:28 +08:00
|
|
|
|
|
|
|
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) {
|
2021-10-05 20:02:53 +08:00
|
|
|
if (If->isConsteval()) {
|
|
|
|
OS << "if ";
|
|
|
|
if (If->isNegatedConsteval())
|
|
|
|
OS << "!";
|
|
|
|
OS << "consteval";
|
|
|
|
OS << NL;
|
|
|
|
PrintStmt(If->getThen());
|
|
|
|
if (Stmt *Else = If->getElse()) {
|
|
|
|
Indent();
|
|
|
|
OS << "else";
|
|
|
|
PrintStmt(Else);
|
|
|
|
OS << NL;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2019-06-03 23:57:25 +08:00
|
|
|
if (Node->isAsmGoto())
|
|
|
|
OS << "goto ";
|
|
|
|
|
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 ||
|
2019-06-03 23:57:25 +08:00
|
|
|
Node->getNumClobbers() != 0 || Node->getNumLabels() != 0)
|
2007-11-22 09:36:19 +08:00
|
|
|
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
|
2019-06-03 23:57:25 +08:00
|
|
|
if (Node->getNumInputs() != 0 || Node->getNumClobbers() != 0 ||
|
|
|
|
Node->getNumLabels() != 0)
|
2007-11-22 09:36:19 +08:00
|
|
|
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
|
2019-06-03 23:57:25 +08:00
|
|
|
if (Node->getNumClobbers() != 0 || Node->getNumLabels())
|
2007-11-22 09:36:19 +08:00
|
|
|
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
|
|
|
|
2019-06-03 23:57:25 +08:00
|
|
|
// Labels
|
|
|
|
if (Node->getNumLabels() != 0)
|
|
|
|
OS << " : ";
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = Node->getNumLabels(); i != e; ++i) {
|
|
|
|
if (i != 0)
|
|
|
|
OS << ", ";
|
|
|
|
OS << Node->getLabelName(i);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2021-10-26 22:53:33 +08:00
|
|
|
for (ObjCAtCatchStmt *catchStmt : Node->catch_stmts()) {
|
2007-11-03 02:16:07 +08:00
|
|
|
Indent() << "@catch(";
|
2021-10-26 22:53:33 +08:00
|
|
|
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
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2021-03-04 07:15:32 +08:00
|
|
|
void StmtPrinter::VisitOMPCanonicalLoop(OMPCanonicalLoop *Node) {
|
|
|
|
PrintStmt(Node->getLoopStmt());
|
|
|
|
}
|
|
|
|
|
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())
|
2020-07-07 01:32:11 +08:00
|
|
|
PrintStmt(S->getRawStmt());
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
2014-02-27 16:29:12 +08:00
|
|
|
|
2021-09-18 05:03:01 +08:00
|
|
|
void StmtPrinter::VisitOMPMetaDirective(OMPMetaDirective *Node) {
|
|
|
|
Indent() << "#pragma omp metadirective";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2021-02-13 03:26:59 +08:00
|
|
|
void StmtPrinter::VisitOMPTileDirective(OMPTileDirective *Node) {
|
|
|
|
Indent() << "#pragma omp tile";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2021-06-11 03:24:17 +08:00
|
|
|
void StmtPrinter::VisitOMPUnrollDirective(OMPUnrollDirective *Node) {
|
|
|
|
Indent() << "#pragma omp unroll";
|
|
|
|
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 << " (";
|
2019-11-16 02:19:17 +08:00
|
|
|
Node->getDirectiveName().printName(OS, Policy);
|
2014-07-21 17:42:05 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-12-06 02:43:48 +08:00
|
|
|
void StmtPrinter::VisitOMPParallelMasterDirective(
|
|
|
|
OMPParallelMasterDirective *Node) {
|
|
|
|
Indent() << "#pragma omp parallel master";
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2020-02-28 22:52:15 +08:00
|
|
|
void StmtPrinter::VisitOMPDepobjDirective(OMPDepobjDirective *Node) {
|
|
|
|
Indent() << "#pragma omp depobj";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2020-03-20 19:03:01 +08:00
|
|
|
void StmtPrinter::VisitOMPScanDirective(OMPScanDirective *Node) {
|
|
|
|
Indent() << "#pragma omp scan";
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-10-11 04:13:02 +08:00
|
|
|
void StmtPrinter::VisitOMPMasterTaskLoopDirective(
|
|
|
|
OMPMasterTaskLoopDirective *Node) {
|
|
|
|
Indent() << "#pragma omp master taskloop";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2019-10-19 00:47:35 +08:00
|
|
|
void StmtPrinter::VisitOMPMasterTaskLoopSimdDirective(
|
|
|
|
OMPMasterTaskLoopSimdDirective *Node) {
|
|
|
|
Indent() << "#pragma omp master taskloop simd";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2019-10-15 01:17:41 +08:00
|
|
|
void StmtPrinter::VisitOMPParallelMasterTaskLoopDirective(
|
|
|
|
OMPParallelMasterTaskLoopDirective *Node) {
|
|
|
|
Indent() << "#pragma omp parallel master taskloop";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2019-10-25 22:27:13 +08:00
|
|
|
void StmtPrinter::VisitOMPParallelMasterTaskLoopSimdDirective(
|
|
|
|
OMPParallelMasterTaskLoopSimdDirective *Node) {
|
|
|
|
Indent() << "#pragma omp parallel master taskloop simd";
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2021-03-16 04:09:46 +08:00
|
|
|
void StmtPrinter::VisitOMPInteropDirective(OMPInteropDirective *Node) {
|
|
|
|
Indent() << "#pragma omp interop";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2021-03-23 09:13:29 +08:00
|
|
|
void StmtPrinter::VisitOMPDispatchDirective(OMPDispatchDirective *Node) {
|
|
|
|
Indent() << "#pragma omp dispatch";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2021-04-10 03:00:36 +08:00
|
|
|
void StmtPrinter::VisitOMPMaskedDirective(OMPMaskedDirective *Node) {
|
|
|
|
Indent() << "#pragma omp masked";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2021-10-28 23:10:40 +08:00
|
|
|
void StmtPrinter::VisitOMPGenericLoopDirective(OMPGenericLoopDirective *Node) {
|
|
|
|
Indent() << "#pragma omp loop";
|
|
|
|
PrintOMPExecutableDirective(Node);
|
|
|
|
}
|
|
|
|
|
2006-11-05 04:18:38 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Expr printing methods.
|
|
|
|
//===----------------------------------------------------------------------===//
|
2006-11-04 15:16:25 +08:00
|
|
|
|
Implement __builtin_LINE() et. al. to support source location capture.
Summary:
This patch implements the source location builtins `__builtin_LINE(), `__builtin_FUNCTION()`, `__builtin_FILE()` and `__builtin_COLUMN()`. These builtins are needed to implement [`std::experimental::source_location`](https://rawgit.com/cplusplus/fundamentals-ts/v2/main.html#reflection.src_loc.creation).
With the exception of `__builtin_COLUMN`, GCC also implements these builtins, and Clangs behavior is intended to match as closely as possible.
Reviewers: rsmith, joerg, aaron.ballman, bogner, majnemer, shafik, martong
Reviewed By: rsmith
Subscribers: rnkovacs, loskutov, riccibruno, mgorny, kunitoki, alexr, majnemer, hfinkel, cfe-commits
Differential Revision: https://reviews.llvm.org/D37035
llvm-svn: 360937
2019-05-17 05:04:15 +08:00
|
|
|
void StmtPrinter::VisitSourceLocExpr(SourceLocExpr *Node) {
|
|
|
|
OS << Node->getBuiltinStr() << "()";
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
2020-09-21 14:16:08 +08:00
|
|
|
if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(Node->getDecl())) {
|
|
|
|
TPOD->printAsExpr(OS);
|
|
|
|
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 ";
|
2021-12-30 08:57:47 +08:00
|
|
|
if (Policy.CleanUglifiedParameters &&
|
|
|
|
isa<ParmVarDecl, NonTypeTemplateParmDecl>(Node->getDecl()) &&
|
|
|
|
Node->getDecl()->getIdentifier())
|
|
|
|
OS << Node->getDecl()->getIdentifier()->deuglifiedName();
|
|
|
|
else
|
|
|
|
Node->getNameInfo().printName(OS, Policy);
|
2021-05-13 01:28:41 +08:00
|
|
|
if (Node->hasExplicitTemplateArgs()) {
|
|
|
|
const TemplateParameterList *TPL = nullptr;
|
|
|
|
if (!Node->hadMultipleCandidates())
|
|
|
|
if (auto *TD = dyn_cast<TemplateDecl>(Node->getDecl()))
|
|
|
|
TPL = TD->getTemplateParameters();
|
|
|
|
printTemplateArgumentList(OS, Node->template_arguments(), Policy, TPL);
|
|
|
|
}
|
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 << "]";
|
|
|
|
}
|
|
|
|
|
2021-04-23 23:22:35 +08:00
|
|
|
void StmtPrinter::VisitSYCLUniqueStableNameExpr(
|
|
|
|
SYCLUniqueStableNameExpr *Node) {
|
|
|
|
OS << "__builtin_sycl_unique_stable_name(";
|
|
|
|
Node->getTypeSourceInfo()->getType().print(OS, Policy);
|
|
|
|
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) {
|
2021-05-13 01:28:41 +08:00
|
|
|
CharacterLiteral::print(Node->getValue(), Node->getKind(), OS);
|
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();
|
2021-06-11 20:19:00 +08:00
|
|
|
OS << toString(Node->getValue(), 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.
|
2019-10-07 21:58:05 +08:00
|
|
|
switch (Node->getType()->castAs<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;
|
2021-03-26 05:27:13 +08:00
|
|
|
case BuiltinType::Int128:
|
|
|
|
break; // no suffix.
|
|
|
|
case BuiltinType::UInt128:
|
|
|
|
break; // no suffix.
|
2007-05-21 13:45:03 +08:00
|
|
|
}
|
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);
|
|
|
|
|
2019-10-07 21:58:05 +08:00
|
|
|
switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
|
2018-06-21 01:19:40 +08:00
|
|
|
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.
|
2019-10-07 21:58:05 +08:00
|
|
|
switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
|
2012-09-20 22:07:17 +08:00
|
|
|
default: llvm_unreachable("Unexpected type for float literal!");
|
|
|
|
case BuiltinType::Half: break; // FIXME: suffix?
|
2021-09-06 17:49:23 +08:00
|
|
|
case BuiltinType::Ibm128: break; // FIXME: No suffix for ibm128 literal
|
2012-09-20 22:07:17 +08:00
|
|
|
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 << ")";
|
|
|
|
}
|
|
|
|
|
2020-06-11 21:08:27 +08:00
|
|
|
void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(
|
|
|
|
UnaryExprOrTypeTraitExpr *Node) {
|
|
|
|
const char *Spelling = getTraitSpelling(Node->getKind());
|
|
|
|
if (Node->getKind() == UETT_AlignOf) {
|
2016-05-19 09:39:10 +08:00
|
|
|
if (Policy.Alignof)
|
2020-06-11 21:08:27 +08:00
|
|
|
Spelling = "alignof";
|
2016-05-19 09:39:10 +08:00
|
|
|
else if (Policy.UnderscoreAlignof)
|
2020-06-11 21:08:27 +08:00
|
|
|
Spelling = "_Alignof";
|
2012-07-01 05:33:57 +08:00
|
|
|
else
|
2020-06-11 21:08:27 +08:00
|
|
|
Spelling = "__alignof";
|
2011-03-12 03:24:49 +08:00
|
|
|
}
|
2020-06-11 21:08:27 +08:00
|
|
|
|
|
|
|
OS << Spelling;
|
|
|
|
|
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-11-13 03:46:19 +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
|
|
|
}
|
|
|
|
|
[Matrix] Implement matrix index expressions ([][]).
This patch implements matrix index expressions
(matrix[RowIdx][ColumnIdx]).
It does so by introducing a new MatrixSubscriptExpr(Base, RowIdx, ColumnIdx).
MatrixSubscriptExprs are built in 2 steps in ActOnMatrixSubscriptExpr. First,
if the base of a subscript is of matrix type, we create a incomplete
MatrixSubscriptExpr(base, idx, nullptr). Second, if the base is an incomplete
MatrixSubscriptExpr, we create a complete
MatrixSubscriptExpr(base->getBase(), base->getRowIdx(), idx)
Similar to vector elements, it is not possible to take the address of
a MatrixSubscriptExpr.
For CodeGen, a new MatrixElt type is added to LValue, which is very
similar to VectorElt. The only difference is that we may need to cast
the type of the base from an array to a vector type when accessing it.
Reviewers: rjmccall, anemet, Bigcheese, rsmith, martong
Reviewed By: rjmccall
Differential Revision: https://reviews.llvm.org/D76791
2020-06-02 02:42:03 +08:00
|
|
|
void StmtPrinter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *Node) {
|
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << "[";
|
|
|
|
PrintExpr(Node->getRowIdx());
|
|
|
|
OS << "]";
|
|
|
|
OS << "[";
|
|
|
|
PrintExpr(Node->getColumnIdx());
|
|
|
|
OS << "]";
|
|
|
|
}
|
|
|
|
|
2015-08-25 22:24:04 +08:00
|
|
|
void StmtPrinter::VisitOMPArraySectionExpr(OMPArraySectionExpr *Node) {
|
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
OS << "[";
|
|
|
|
if (Node->getLowerBound())
|
|
|
|
PrintExpr(Node->getLowerBound());
|
2020-07-10 02:27:32 +08:00
|
|
|
if (Node->getColonLocFirst().isValid()) {
|
2015-09-11 12:54:28 +08:00
|
|
|
OS << ":";
|
|
|
|
if (Node->getLength())
|
|
|
|
PrintExpr(Node->getLength());
|
|
|
|
}
|
2020-07-10 02:27:32 +08:00
|
|
|
if (Node->getColonLocSecond().isValid()) {
|
|
|
|
OS << ":";
|
|
|
|
if (Node->getStride())
|
|
|
|
PrintExpr(Node->getStride());
|
|
|
|
}
|
2015-08-25 22:24:04 +08:00
|
|
|
OS << "]";
|
|
|
|
}
|
|
|
|
|
[OPENMP50]Add basic support for array-shaping operation.
Summary:
Added basic representation and parsing/sema handling of array-shaping
operations. Array shaping expression is an expression of form ([s0]..[sn])base,
where s0, ..., sn must be a positive integer, base - a pointer. This
expression is a kind of cast operation that converts pointer expression
into an array-like kind of expression.
Reviewers: rjmccall, rsmith, jdoerfert
Subscribers: guansong, arphaman, cfe-commits, caomhin, kkwli0
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74144
2020-02-05 22:33:05 +08:00
|
|
|
void StmtPrinter::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *Node) {
|
|
|
|
OS << "(";
|
|
|
|
for (Expr *E : Node->getDimensions()) {
|
|
|
|
OS << "[";
|
|
|
|
PrintExpr(E);
|
|
|
|
OS << "]";
|
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
PrintExpr(Node->getBase());
|
|
|
|
}
|
|
|
|
|
2020-04-02 03:06:38 +08:00
|
|
|
void StmtPrinter::VisitOMPIteratorExpr(OMPIteratorExpr *Node) {
|
|
|
|
OS << "iterator(";
|
|
|
|
for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) {
|
|
|
|
auto *VD = cast<ValueDecl>(Node->getIteratorDecl(I));
|
|
|
|
VD->getType().print(OS, Policy);
|
|
|
|
const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I);
|
|
|
|
OS << " " << VD->getName() << " = ";
|
|
|
|
PrintExpr(Range.Begin);
|
|
|
|
OS << ":";
|
|
|
|
PrintExpr(Range.End);
|
|
|
|
if (Range.Step) {
|
|
|
|
OS << ":";
|
|
|
|
PrintExpr(Range.Step);
|
|
|
|
}
|
|
|
|
if (I < E - 1)
|
|
|
|
OS << ", ";
|
|
|
|
}
|
|
|
|
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();
|
2021-05-13 01:28:41 +08:00
|
|
|
const TemplateParameterList *TPL = nullptr;
|
|
|
|
if (auto *FD = dyn_cast<FunctionDecl>(Node->getMemberDecl())) {
|
|
|
|
if (!Node->hadMultipleCandidates())
|
|
|
|
if (auto *FTD = FD->getPrimaryTemplate())
|
|
|
|
TPL = FTD->getTemplateParameters();
|
|
|
|
} else if (auto *VTSD =
|
|
|
|
dyn_cast<VarTemplateSpecializationDecl>(Node->getMemberDecl()))
|
|
|
|
TPL = VTSD->getSpecializedTemplate()->getTemplateParameters();
|
2010-08-20 07:49:38 +08:00
|
|
|
if (Node->hasExplicitTemplateArgs())
|
2021-05-13 01:28:41 +08:00
|
|
|
printTemplateArgumentList(OS, Node->template_arguments(), Policy, TPL);
|
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 &&
|
2021-11-30 03:06:52 +08:00
|
|
|
Node->getOp() != AtomicExpr::AO__opencl_atomic_load &&
|
|
|
|
Node->getOp() != AtomicExpr::AO__hip_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) {
|
|
|
|
OverloadedOperatorKind Kind = Node->getOperator();
|
|
|
|
if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
|
|
|
|
if (Node->getNumArgs() == 1) {
|
2019-06-15 04:01:51 +08:00
|
|
|
OS << getOperatorSpelling(Kind) << ' ';
|
2008-11-15 00:09:21 +08:00
|
|
|
PrintExpr(Node->getArg(0));
|
|
|
|
} else {
|
|
|
|
PrintExpr(Node->getArg(0));
|
2019-06-15 04:01:51 +08:00
|
|
|
OS << ' ' << getOperatorSpelling(Kind);
|
2008-11-15 00:09:21 +08:00
|
|
|
}
|
2012-10-13 06:45:14 +08:00
|
|
|
} else if (Kind == OO_Arrow) {
|
|
|
|
PrintExpr(Node->getArg(0));
|
2022-02-09 01:09:03 +08:00
|
|
|
} else if (Kind == OO_Call || Kind == OO_Subscript) {
|
2008-11-15 00:09:21 +08:00
|
|
|
PrintExpr(Node->getArg(0));
|
2022-02-09 01:09:03 +08:00
|
|
|
OS << (Kind == OO_Call ? '(' : '[');
|
2008-11-15 00:09:21 +08:00
|
|
|
for (unsigned ArgIdx = 1; ArgIdx < Node->getNumArgs(); ++ArgIdx) {
|
|
|
|
if (ArgIdx > 1)
|
|
|
|
OS << ", ";
|
|
|
|
if (!isa<CXXDefaultArgExpr>(Node->getArg(ArgIdx)))
|
|
|
|
PrintExpr(Node->getArg(ArgIdx));
|
|
|
|
}
|
2022-02-09 01:09:03 +08:00
|
|
|
OS << (Kind == OO_Call ? ')' : ']');
|
2008-11-15 00:09:21 +08:00
|
|
|
} else if (Node->getNumArgs() == 1) {
|
2019-06-15 04:01:51 +08:00
|
|
|
OS << getOperatorSpelling(Kind) << ' ';
|
2008-11-15 00:09:21 +08:00
|
|
|
PrintExpr(Node->getArg(0));
|
|
|
|
} else if (Node->getNumArgs() == 2) {
|
|
|
|
PrintExpr(Node->getArg(0));
|
2019-06-15 04:01:51 +08:00
|
|
|
OS << ' ' << getOperatorSpelling(Kind) << ' ';
|
2008-11-15 00:09:21 +08:00
|
|
|
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 << ")";
|
|
|
|
}
|
|
|
|
|
2019-10-19 08:04:38 +08:00
|
|
|
void StmtPrinter::VisitCXXRewrittenBinaryOperator(
|
|
|
|
CXXRewrittenBinaryOperator *Node) {
|
|
|
|
CXXRewrittenBinaryOperator::DecomposedForm Decomposed =
|
|
|
|
Node->getDecomposedForm();
|
|
|
|
PrintExpr(const_cast<Expr*>(Decomposed.LHS));
|
|
|
|
OS << ' ' << BinaryOperator::getOpcodeStr(Decomposed.Opcode) << ' ';
|
|
|
|
PrintExpr(const_cast<Expr*>(Decomposed.RHS));
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-07-03 02:28:13 +08:00
|
|
|
void StmtPrinter::VisitBuiltinBitCastExpr(BuiltinBitCastExpr *Node) {
|
|
|
|
OS << "__builtin_bit_cast(";
|
|
|
|
Node->getTypeInfoAsWritten()->getType().print(OS, Policy);
|
|
|
|
OS << ", ";
|
|
|
|
PrintExpr(Node->getSubExpr());
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
2020-05-18 18:02:01 +08:00
|
|
|
void StmtPrinter::VisitCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *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) {
|
2021-05-13 01:28:41 +08:00
|
|
|
const TemplateParameterList *TPL = nullptr;
|
|
|
|
if (!DRE->hadMultipleCandidates())
|
|
|
|
if (const auto *TD = dyn_cast<TemplateDecl>(DRE->getDecl()))
|
|
|
|
TPL = TD->getTemplateParameters();
|
2015-10-08 08:17:59 +08:00
|
|
|
OS << "operator\"\"" << Node->getUDSuffix()->getName();
|
2021-05-13 01:28:41 +08:00
|
|
|
printTemplateArgumentList(OS, Args->asArray(), Policy, TPL);
|
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());
|
2021-06-11 20:19:00 +08:00
|
|
|
OS << toString(Int->getValue(), 10, /*isSigned*/false);
|
2012-03-08 17:02:38 +08:00
|
|
|
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
|
|
|
|
2019-05-05 20:35:12 +08:00
|
|
|
if (C->isPackExpansion())
|
|
|
|
OS << "...";
|
|
|
|
|
2020-07-16 18:47:44 +08:00
|
|
|
if (Node->isInitCapture(C)) {
|
|
|
|
VarDecl *D = C->getCapturedVar();
|
|
|
|
|
|
|
|
llvm::StringRef Pre;
|
|
|
|
llvm::StringRef Post;
|
|
|
|
if (D->getInitStyle() == VarDecl::CallInit &&
|
|
|
|
!isa<ParenListExpr>(D->getInit())) {
|
|
|
|
Pre = "(";
|
|
|
|
Post = ")";
|
|
|
|
} else if (D->getInitStyle() == VarDecl::CInit) {
|
|
|
|
Pre = " = ";
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << Pre;
|
|
|
|
PrintExpr(D->getInit());
|
|
|
|
OS << Post;
|
|
|
|
}
|
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;
|
|
|
|
}
|
2021-12-30 08:57:47 +08:00
|
|
|
std::string ParamStr =
|
|
|
|
(Policy.CleanUglifiedParameters && P->getIdentifier())
|
|
|
|
? P->getIdentifier()->deuglifiedName().str()
|
|
|
|
: P->getNameAsString();
|
2014-03-08 01:50:17 +08:00
|
|
|
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";
|
|
|
|
|
2019-10-07 21:58:05 +08:00
|
|
|
auto *Proto = Method->getType()->castAs<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-28 00:20:45 +08:00
|
|
|
if (Policy.TerseOutput)
|
|
|
|
OS << "{}";
|
|
|
|
else
|
2020-06-18 19:51:11 +08:00
|
|
|
PrintRawCompoundStmt(Node->getCompoundStmtBody());
|
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;
|
2019-05-06 11:47:15 +08:00
|
|
|
if (Optional<Expr *> Size = E->getArraySize()) {
|
2008-12-03 06:08:59 +08:00
|
|
|
llvm::raw_string_ostream s(TypeS);
|
2013-02-22 22:19:01 +08:00
|
|
|
s << '[';
|
2019-05-06 11:47:15 +08:00
|
|
|
if (*Size)
|
|
|
|
(*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
|
|
|
void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) {
|
2020-06-11 21:08:27 +08:00
|
|
|
OS << getTraitSpelling(E->getTrait()) << "(";
|
2012-02-24 15:38:34 +08:00
|
|
|
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) {
|
2020-06-11 21:08:27 +08:00
|
|
|
OS << getTraitSpelling(E->getTrait()) << '(';
|
2013-02-22 22:19:01 +08:00
|
|
|
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) {
|
2020-06-11 21:08:27 +08:00
|
|
|
OS << getTraitSpelling(E->getTrait()) << '(';
|
2013-02-22 22:19:01 +08:00
|
|
|
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){
|
2019-11-17 18:41:55 +08:00
|
|
|
PrintExpr(Node->getSubExpr());
|
2011-06-22 01:03:29 +08:00
|
|
|
}
|
|
|
|
|
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 << ")";
|
|
|
|
}
|
|
|
|
|
2019-10-15 23:24:26 +08:00
|
|
|
void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
|
|
|
|
NestedNameSpecifierLoc NNS = E->getNestedNameSpecifierLoc();
|
|
|
|
if (NNS)
|
|
|
|
NNS.getNestedNameSpecifier()->print(OS, Policy);
|
|
|
|
if (E->getTemplateKWLoc().isValid())
|
|
|
|
OS << "template ";
|
|
|
|
OS << E->getFoundDecl()->getName();
|
|
|
|
printTemplateArgumentList(OS, E->getTemplateArgsAsWritten()->arguments(),
|
2021-05-13 01:28:41 +08:00
|
|
|
Policy,
|
|
|
|
E->getNamedConcept()->getTemplateParameters());
|
2019-10-15 23:24:26 +08:00
|
|
|
}
|
|
|
|
|
2020-01-18 15:11:43 +08:00
|
|
|
void StmtPrinter::VisitRequiresExpr(RequiresExpr *E) {
|
|
|
|
OS << "requires ";
|
|
|
|
auto LocalParameters = E->getLocalParameters();
|
|
|
|
if (!LocalParameters.empty()) {
|
|
|
|
OS << "(";
|
|
|
|
for (ParmVarDecl *LocalParam : LocalParameters) {
|
|
|
|
PrintRawDecl(LocalParam);
|
|
|
|
if (LocalParam != LocalParameters.back())
|
|
|
|
OS << ", ";
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << ") ";
|
|
|
|
}
|
|
|
|
OS << "{ ";
|
|
|
|
auto Requirements = E->getRequirements();
|
|
|
|
for (concepts::Requirement *Req : Requirements) {
|
|
|
|
if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req)) {
|
|
|
|
if (TypeReq->isSubstitutionFailure())
|
|
|
|
OS << "<<error-type>>";
|
|
|
|
else
|
|
|
|
TypeReq->getType()->getType().print(OS, Policy);
|
|
|
|
} else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req)) {
|
|
|
|
if (ExprReq->isCompound())
|
|
|
|
OS << "{ ";
|
|
|
|
if (ExprReq->isExprSubstitutionFailure())
|
|
|
|
OS << "<<error-expression>>";
|
|
|
|
else
|
|
|
|
PrintExpr(ExprReq->getExpr());
|
|
|
|
if (ExprReq->isCompound()) {
|
|
|
|
OS << " }";
|
|
|
|
if (ExprReq->getNoexceptLoc().isValid())
|
|
|
|
OS << " noexcept";
|
|
|
|
const auto &RetReq = ExprReq->getReturnTypeRequirement();
|
|
|
|
if (!RetReq.isEmpty()) {
|
|
|
|
OS << " -> ";
|
|
|
|
if (RetReq.isSubstitutionFailure())
|
|
|
|
OS << "<<error-type>>";
|
|
|
|
else if (RetReq.isTypeConstraint())
|
|
|
|
RetReq.getTypeConstraint()->print(OS, Policy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
auto *NestedReq = cast<concepts::NestedRequirement>(Req);
|
|
|
|
OS << "requires ";
|
|
|
|
if (NestedReq->isSubstitutionFailure())
|
|
|
|
OS << "<<error-expression>>";
|
|
|
|
else
|
|
|
|
PrintExpr(NestedReq->getConstraintExpr());
|
|
|
|
}
|
|
|
|
OS << "; ";
|
|
|
|
}
|
|
|
|
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
|
|
|
}
|
|
|
|
|
[AST] Add RecoveryExpr to retain expressions on semantic errors
Normally clang avoids creating expressions when it encounters semantic
errors, even if the parser knows which expression to produce.
This works well for the compiler. However, this is not ideal for
source-level tools that have to deal with broken code, e.g. clangd is
not able to provide navigation features even for names that compiler
knows how to resolve.
The new RecoveryExpr aims to capture the minimal set of information
useful for the tools that need to deal with incorrect code:
source range of the expression being dropped,
subexpressions of the expression.
We aim to make constructing RecoveryExprs as simple as possible to
ensure writing code to avoid dropping expressions is easy.
Producing RecoveryExprs can result in new code paths being taken in the
frontend. In particular, clang can produce some new diagnostics now and
we aim to suppress bogus ones based on Expr::containsErrors.
We deliberately produce RecoveryExprs only in the parser for now to
minimize the code affected by this patch. Producing RecoveryExprs in
Sema potentially allows to preserve more information (e.g. type of an
expression), but also results in more code being affected. E.g.
SFINAE checks will have to take presence of RecoveryExprs into account.
Initial implementation only works in C++ mode, as it relies on compiler
postponing diagnostics on dependent expressions. C and ObjC often do not
do this, so they require more work to make sure we do not produce too
many bogus diagnostics on the new expressions.
See documentation of RecoveryExpr for more details.
original patch from Ilya
This change is based on https://reviews.llvm.org/D61722
Reviewers: sammccall, rsmith
Reviewed By: sammccall, rsmith
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69330
2020-03-19 23:30:40 +08:00
|
|
|
void StmtPrinter::VisitRecoveryExpr(RecoveryExpr *Node) {
|
|
|
|
OS << "<recovery-expr>(";
|
|
|
|
const char *Sep = "";
|
|
|
|
for (Expr *E : Node->subExpressions()) {
|
|
|
|
OS << Sep;
|
|
|
|
PrintExpr(E);
|
|
|
|
Sep = ", ";
|
|
|
|
}
|
|
|
|
OS << ')';
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
[analyzer][AST] print() JSONify: Stmt implementation
Summary:
This patch also adds a function called `JsonFormat()` which:
- Flattens the string so removes the new-lines.
- Escapes double quotes.
Reviewers: NoQ, xazax.hun, ravikandhadai, baloghadamsoftware, Szelethus
Reviewed By: NoQ
Subscribers: cfe-commits, szepet, rnkovacs, a.sidorin, mikhail.ramalho,
donat.nagy, dkrupp
Tags: #clang
Differential Revision: https://reviews.llvm.org/D62494
llvm-svn: 362000
2019-05-30 02:17:18 +08:00
|
|
|
void Stmt::printPretty(raw_ostream &Out, PrinterHelper *Helper,
|
2017-08-17 21:41:55 +08:00
|
|
|
const PrintingPolicy &Policy, unsigned Indentation,
|
[analyzer][AST] print() JSONify: Stmt implementation
Summary:
This patch also adds a function called `JsonFormat()` which:
- Flattens the string so removes the new-lines.
- Escapes double quotes.
Reviewers: NoQ, xazax.hun, ravikandhadai, baloghadamsoftware, Szelethus
Reviewed By: NoQ
Subscribers: cfe-commits, szepet, rnkovacs, a.sidorin, mikhail.ramalho,
donat.nagy, dkrupp
Tags: #clang
Differential Revision: https://reviews.llvm.org/D62494
llvm-svn: 362000
2019-05-30 02:17:18 +08:00
|
|
|
StringRef NL, const ASTContext *Context) const {
|
|
|
|
StmtPrinter P(Out, Helper, Policy, Indentation, NL, Context);
|
|
|
|
P.Visit(const_cast<Stmt *>(this));
|
|
|
|
}
|
|
|
|
|
2021-11-15 12:44:27 +08:00
|
|
|
void Stmt::printPrettyControlled(raw_ostream &Out, PrinterHelper *Helper,
|
|
|
|
const PrintingPolicy &Policy,
|
|
|
|
unsigned Indentation, StringRef NL,
|
|
|
|
const ASTContext *Context) const {
|
|
|
|
StmtPrinter P(Out, Helper, Policy, Indentation, NL, Context);
|
|
|
|
P.PrintControlledStmt(const_cast<Stmt *>(this));
|
|
|
|
}
|
|
|
|
|
[analyzer][AST] print() JSONify: Stmt implementation
Summary:
This patch also adds a function called `JsonFormat()` which:
- Flattens the string so removes the new-lines.
- Escapes double quotes.
Reviewers: NoQ, xazax.hun, ravikandhadai, baloghadamsoftware, Szelethus
Reviewed By: NoQ
Subscribers: cfe-commits, szepet, rnkovacs, a.sidorin, mikhail.ramalho,
donat.nagy, dkrupp
Tags: #clang
Differential Revision: https://reviews.llvm.org/D62494
llvm-svn: 362000
2019-05-30 02:17:18 +08:00
|
|
|
void Stmt::printJson(raw_ostream &Out, PrinterHelper *Helper,
|
|
|
|
const PrintingPolicy &Policy, bool AddQuotes) const {
|
|
|
|
std::string Buf;
|
|
|
|
llvm::raw_string_ostream TempOut(Buf);
|
|
|
|
|
|
|
|
printPretty(TempOut, Helper, Policy);
|
|
|
|
|
|
|
|
Out << JsonFormat(TempOut.str(), AddQuotes);
|
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;
|