clang  14.0.0git
SourceCodeBuilders.cpp
Go to the documentation of this file.
1 //===--- SourceCodeBuilder.cpp ----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/Expr.h"
12 #include "clang/AST/ExprCXX.h"
14 #include "llvm/ADT/Twine.h"
15 #include <string>
16 
17 using namespace clang;
18 using namespace tooling;
19 
21  const Expr *Expr = E.IgnoreImplicit();
22  if (const auto *CE = dyn_cast<CXXConstructExpr>(Expr)) {
23  if (CE->getNumArgs() > 0 &&
24  CE->getArg(0)->getSourceRange() == Expr->getSourceRange())
25  return CE->getArg(0)->IgnoreImplicit();
26  }
27  return Expr;
28 }
29 
31  const Expr *Expr = reallyIgnoreImplicit(E);
32  // We always want parens around unary, binary, and ternary operators, because
33  // they are lower precedence.
34  if (isa<UnaryOperator>(Expr) || isa<BinaryOperator>(Expr) ||
35  isa<AbstractConditionalOperator>(Expr))
36  return true;
37 
38  // We need parens around calls to all overloaded operators except: function
39  // calls, subscripts, and expressions that are already part of an (implicit)
40  // call to operator->. These latter are all in the same precedence level as
41  // dot/arrow and that level is left associative, so they don't need parens
42  // when appearing on the left.
43  if (const auto *Op = dyn_cast<CXXOperatorCallExpr>(Expr))
44  return Op->getOperator() != OO_Call && Op->getOperator() != OO_Subscript &&
45  Op->getOperator() != OO_Arrow;
46 
47  return false;
48 }
49 
51  const Expr *Expr = reallyIgnoreImplicit(E);
52  if (isa<BinaryOperator>(Expr) || isa<AbstractConditionalOperator>(Expr))
53  return true;
54 
55  if (const auto *Op = dyn_cast<CXXOperatorCallExpr>(Expr))
56  return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
57  Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
58  Op->getOperator() != OO_Subscript;
59 
60  return false;
61 }
62 
64  const ASTContext &Context) {
65  StringRef Text = getText(E, Context);
66  if (Text.empty())
67  return llvm::None;
68  if (mayEverNeedParens(E))
69  return ("(" + Text + ")").str();
70  return Text.str();
71 }
72 
74 tooling::buildDereference(const Expr &E, const ASTContext &Context) {
75  if (const auto *Op = dyn_cast<UnaryOperator>(&E))
76  if (Op->getOpcode() == UO_AddrOf) {
77  // Strip leading '&'.
78  StringRef Text =
79  getText(*Op->getSubExpr()->IgnoreParenImpCasts(), Context);
80  if (Text.empty())
81  return llvm::None;
82  return Text.str();
83  }
84 
85  StringRef Text = getText(E, Context);
86  if (Text.empty())
87  return llvm::None;
88  // Add leading '*'.
90  return ("*(" + Text + ")").str();
91  return ("*" + Text).str();
92 }
93 
95  const ASTContext &Context) {
96  if (E.isImplicitCXXThis())
97  return std::string("this");
98  if (const auto *Op = dyn_cast<UnaryOperator>(&E))
99  if (Op->getOpcode() == UO_Deref) {
100  // Strip leading '*'.
101  StringRef Text =
102  getText(*Op->getSubExpr()->IgnoreParenImpCasts(), Context);
103  if (Text.empty())
104  return llvm::None;
105  return Text.str();
106  }
107  // Add leading '&'.
108  StringRef Text = getText(E, Context);
109  if (Text.empty())
110  return llvm::None;
112  return ("&(" + Text + ")").str();
113  }
114  return ("&" + Text).str();
115 }
116 
118  const ASTContext &Context) {
119  if (const auto *Op = llvm::dyn_cast<UnaryOperator>(&E))
120  if (Op->getOpcode() == UO_Deref) {
121  // Strip leading '*', add following '->'.
122  const Expr *SubExpr = Op->getSubExpr()->IgnoreParenImpCasts();
123  StringRef DerefText = getText(*SubExpr, Context);
124  if (DerefText.empty())
125  return llvm::None;
126  if (needParensBeforeDotOrArrow(*SubExpr))
127  return ("(" + DerefText + ")->").str();
128  return (DerefText + "->").str();
129  }
130 
131  // Add following '.'.
132  StringRef Text = getText(E, Context);
133  if (Text.empty())
134  return llvm::None;
136  return ("(" + Text + ").").str();
137  }
138  return (Text + ".").str();
139 }
140 
142  const ASTContext &Context) {
143  if (const auto *Op = llvm::dyn_cast<UnaryOperator>(&E))
144  if (Op->getOpcode() == UO_AddrOf) {
145  // Strip leading '&', add following '.'.
146  const Expr *SubExpr = Op->getSubExpr()->IgnoreParenImpCasts();
147  StringRef DerefText = getText(*SubExpr, Context);
148  if (DerefText.empty())
149  return llvm::None;
150  if (needParensBeforeDotOrArrow(*SubExpr))
151  return ("(" + DerefText + ").").str();
152  return (DerefText + ".").str();
153  }
154 
155  // Add following '->'.
156  StringRef Text = getText(E, Context);
157  if (Text.empty())
158  return llvm::None;
160  return ("(" + Text + ")->").str();
161  return (Text + "->").str();
162 }
clang::tooling::buildDot
llvm::Optional< std::string > buildDot(const Expr &E, const ASTContext &Context)
Adds a dot to the end of the given expression, but adds parentheses when needed by the syntax,...
Definition: SourceCodeBuilders.cpp:117
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::Expr::IgnoreImplicit
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:2907
clang::Stmt::getSourceRange
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:324
clang::tooling::buildArrow
llvm::Optional< std::string > buildArrow(const Expr &E, const ASTContext &Context)
Adds an arrow to the end of the given expression, but adds parentheses when needed by the syntax,...
Definition: SourceCodeBuilders.cpp:141
llvm::Optional< std::string >
clang::tooling::mayEverNeedParens
bool mayEverNeedParens(const Expr &E)
Determines whether printing this expression in any expression requires parentheses to preserve its me...
Definition: SourceCodeBuilders.cpp:30
clang::tooling::buildParens
llvm::Optional< std::string > buildParens(const Expr &E, const ASTContext &Context)
Builds source for an expression, adding parens if needed for unambiguous parsing.
Definition: SourceCodeBuilders.cpp:63
clang::tooling::buildAddressOf
llvm::Optional< std::string > buildAddressOf(const Expr &E, const ASTContext &Context)
Builds idiomatic source for taking the address of E: prefix with & but simplify when it already begin...
Definition: SourceCodeBuilders.cpp:94
clang::ASTContext
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:212
SourceCodeBuilders.h
Expr.h
ASTContext.h
ExprCXX.h
clang::tooling::buildDereference
llvm::Optional< std::string > buildDereference(const Expr &E, const ASTContext &Context)
Builds idiomatic source for the dereferencing of E: prefix with * but simplify when it already begins...
Definition: SourceCodeBuilders.cpp:74
clang::Expr::isImplicitCXXThis
bool isImplicitCXXThis() const
Whether this expression is an implicit reference to 'this' in C++.
Definition: Expr.cpp:3095
clang::tooling::reallyIgnoreImplicit
const Expr * reallyIgnoreImplicit(const Expr &E)
Definition: SourceCodeBuilders.cpp:20
SourceCode.h
clang::Expr::IgnoreParenImpCasts
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:2919
clang
Definition: CalledOnceCheck.h:17
Text
StringRef Text
Definition: Format.cpp:2334
clang::tooling::needParensBeforeDotOrArrow
bool needParensBeforeDotOrArrow(const Expr &E)
Determines whether printing this expression to the left of a dot or arrow operator requires a parenth...
Definition: SourceCodeBuilders.h:39
clang::tooling::getText
StringRef getText(CharSourceRange Range, const ASTContext &Context)
Returns the source-code text in the specified range.
Definition: SourceCode.cpp:31
clang::tooling::needParensAfterUnaryOperator
bool needParensAfterUnaryOperator(const Expr &E)
Determines whether printing this expression to the right of a unary operator requires a parentheses t...
Definition: SourceCodeBuilders.cpp:50
clang::Expr
This represents one expression.
Definition: Expr.h:109