clang  10.0.0svn
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 (const auto *Op = dyn_cast<UnaryOperator>(&E))
97  if (Op->getOpcode() == UO_Deref) {
98  // Strip leading '*'.
99  StringRef Text =
100  getText(*Op->getSubExpr()->IgnoreParenImpCasts(), Context);
101  if (Text.empty())
102  return llvm::None;
103  return Text.str();
104  }
105  // Add leading '&'.
106  StringRef Text = getText(E, Context);
107  if (Text.empty())
108  return llvm::None;
110  return ("&(" + Text + ")").str();
111  }
112  return ("&" + Text).str();
113 }
114 
116  const ASTContext &Context) {
117  if (const auto *Op = llvm::dyn_cast<UnaryOperator>(&E))
118  if (Op->getOpcode() == UO_Deref) {
119  // Strip leading '*', add following '->'.
120  const Expr *SubExpr = Op->getSubExpr()->IgnoreParenImpCasts();
121  StringRef DerefText = getText(*SubExpr, Context);
122  if (DerefText.empty())
123  return llvm::None;
124  if (needParensBeforeDotOrArrow(*SubExpr))
125  return ("(" + DerefText + ")->").str();
126  return (DerefText + "->").str();
127  }
128 
129  // Add following '.'.
130  StringRef Text = getText(E, Context);
131  if (Text.empty())
132  return llvm::None;
134  return ("(" + Text + ").").str();
135  }
136  return (Text + ".").str();
137 }
138 
140  const ASTContext &Context) {
141  if (const auto *Op = llvm::dyn_cast<UnaryOperator>(&E))
142  if (Op->getOpcode() == UO_AddrOf) {
143  // Strip leading '&', add following '.'.
144  const Expr *SubExpr = Op->getSubExpr()->IgnoreParenImpCasts();
145  StringRef DerefText = getText(*SubExpr, Context);
146  if (DerefText.empty())
147  return llvm::None;
148  if (needParensBeforeDotOrArrow(*SubExpr))
149  return ("(" + DerefText + ").").str();
150  return (DerefText + ".").str();
151  }
152 
153  // Add following '->'.
154  StringRef Text = getText(E, Context);
155  if (Text.empty())
156  return llvm::None;
158  return ("(" + Text + ")->").str();
159  return (Text + "->").str();
160 }
Defines the clang::ASTContext interface.
const Expr * reallyIgnoreImplicit(const Expr &E)
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...
StringRef getText(CharSourceRange Range, const ASTContext &Context)
Returns the source-code text in the specified range.
Definition: SourceCode.cpp:17
Defines the clang::Expr interface and subclasses for C++ expressions.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:160
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...
bool needParensBeforeDotOrArrow(const Expr &E)
Determines whether printing this expression to the left of a dot or arrow operator requires a parenth...
This represents one expression.
Definition: Expr.h:108
This file collects facilities for generating source code strings.
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...
llvm::Optional< std::string > buildParens(const Expr &E, const ASTContext &Context)
Builds source for an expression, adding parens if needed for unambiguous parsing. ...
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...
Dataflow Directional Tag Classes.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:2966
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:2958
bool needParensAfterUnaryOperator(const Expr &E)
Determines whether printing this expression to the right of a unary operator requires a parentheses t...
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:262
StringRef Text
Definition: Format.cpp:1808
A node that&#39;s not selected.
bool mayEverNeedParens(const Expr &E)
Determines whether printing this expression in any expression requires parentheses to preserve its me...