clang 24.0.0git
ExprUtils.cpp
Go to the documentation of this file.
1//===--- ExprUtils.cpp - Shared expression emission queries ---------------===//
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/Attr.h"
11#include "clang/AST/ExprCXX.h"
12
13namespace clang::CodeGenUtils {
14
16 const VariableArrayType *VLA) {
17 QualType EltType;
18 do {
19 EltType = VLA->getElementType();
20 } while ((VLA = Ctx.getAsVariableArrayType(EltType)));
21 return EltType;
22}
23
24bool isBlockVarRef(const Expr *E) {
25 // Make sure we look through parens.
26 E = E->IgnoreParens();
27
28 // Check for a direct reference to a __block variable.
29 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
30 const VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl());
31 return (Var && Var->hasAttr<BlocksAttr>());
32 }
33
34 // More complicated stuff.
35
36 // Binary operators.
37 if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
38 // For an assignment or pointer-to-member operation, just care
39 // about the LHS.
40 if (Op->isAssignmentOp() || Op->isPtrMemOp())
41 return isBlockVarRef(Op->getLHS());
42
43 // For a comma, just care about the RHS.
44 if (Op->getOpcode() == BO_Comma)
45 return isBlockVarRef(Op->getRHS());
46
47 // FIXME: pointer arithmetic?
48 return false;
49
50 // Check both sides of a conditional operator.
51 } else if (const AbstractConditionalOperator *Op =
52 dyn_cast<AbstractConditionalOperator>(E)) {
53 return isBlockVarRef(Op->getTrueExpr()) ||
54 isBlockVarRef(Op->getFalseExpr());
55
56 // OVEs are required to support BinaryConditionalOperators.
57 } else if (const OpaqueValueExpr *Op = dyn_cast<OpaqueValueExpr>(E)) {
58 if (const Expr *Src = Op->getSourceExpr())
59 return isBlockVarRef(Src);
60
61 // Casts are necessary to get things like (*(int*)&var) = foo().
62 // We don't really care about the kind of cast here, except
63 // we don't want to look through l2r casts, because it's okay
64 // to get the *value* in a __block variable.
65 } else if (const CastExpr *Cast = dyn_cast<CastExpr>(E)) {
66 if (Cast->getCastKind() == CK_LValueToRValue)
67 return false;
68 return isBlockVarRef(Cast->getSubExpr());
69
70 // Handle unary operators. Again, just aggressively look through
71 // it, ignoring the operation.
72 } else if (const UnaryOperator *UOp = dyn_cast<UnaryOperator>(E)) {
73 return isBlockVarRef(UOp->getSubExpr());
74
75 // Look into the base of a field access.
76 } else if (const MemberExpr *Mem = dyn_cast<MemberExpr>(E)) {
77 return isBlockVarRef(Mem->getBase());
78
79 // Look into the base of a subscript.
80 } else if (const ArraySubscriptExpr *Sub = dyn_cast<ArraySubscriptExpr>(E)) {
81 return isBlockVarRef(Sub->getBase());
82 }
83
84 return false;
85}
86
88 const ASTContext &Ctx) {
89 // Anything that is an integer or floating point constant is fine.
90 return E->IgnoreParens()->isEvaluatable(Ctx);
91
92 // Even non-volatile automatic variables can't be evaluated unconditionally.
93 // Referencing a thread_local may cause non-trivial initialization work to
94 // occur. If we're inside a lambda and one of the variables is from the scope
95 // outside the lambda, that function may have returned already. Reading its
96 // locals is a bad idea. Also, these reads may introduce races there didn't
97 // exist in the source-level program.
98}
99
100bool isTrivialFiller(const Expr *E) {
101 if (!E)
102 return true;
103
105 return true;
106
107 if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
108 if (ILE->getNumInits())
109 return false;
110 return isTrivialFiller(ILE->getArrayFiller());
111 }
112
113 if (const auto *Cons = dyn_cast_or_null<CXXConstructExpr>(E))
114 return Cons->getConstructor()->isDefaultConstructor() &&
115 Cons->getConstructor()->isTrivial();
116
117 // FIXME: Are there other cases where we can avoid emitting an initializer?
118 return false;
119}
120
122 for (const FunctionDecl *PD = FD; PD; PD = PD->getPreviousDecl())
123 if (!PD->isInlineBuiltinDeclaration())
124 return false;
125 return true;
126}
127
129 assert(Type.isCanonical());
130 assert(!Type->isReferenceType());
131
132 // Must be const-qualified but non-volatile.
133 Qualifiers Qs = Type.getLocalQualifiers();
134 if (!Qs.hasConst() || Qs.hasVolatile())
135 return false;
136
137 // Otherwise, all object types satisfy this except C++ classes with
138 // mutable subobjects or non-trivial copy/destroy behavior.
139 if (const auto *RT = dyn_cast<RecordType>(Type))
140 if (const auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
141 RD = RD->getDefinitionOrSelf();
142 if (RD->hasMutableFields() || !RD->isTrivial())
143 return false;
144 }
145
146 return true;
147}
148
150 Type = Type.getCanonicalType();
151 if (const auto *Ref = dyn_cast<ReferenceType>(Type)) {
152 if (isConstantEmittableObjectType(Ref->getPointeeType()))
154 return CEK_AsReferenceOnly;
155 }
157 return CEK_AsValueOnly;
158 return CEK_None;
159}
160
161} // namespace clang::CodeGenUtils
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:245
const VariableArrayType * getAsVariableArrayType(QualType T) const
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition Expr.h:4422
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2790
QualType getElementType() const
Definition TypeBase.h:3832
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4107
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3745
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1315
bool hasAttr() const
Definition DeclBase.h:586
This represents one expression.
Definition Expr.h:114
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3125
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
Represents a function declaration or definition.
Definition Decl.h:2071
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3433
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1223
A (possibly-)qualified type.
Definition TypeBase.h:938
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
bool hasConst() const
Definition TypeBase.h:458
bool hasVolatile() const
Definition TypeBase.h:468
The base class of the type hierarchy.
Definition TypeBase.h:1879
bool isReferenceType() const
Definition TypeBase.h:8707
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2313
Represents a variable declaration or definition.
Definition Decl.h:934
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4064
QualType getFixedSizeElementType(const ASTContext &Ctx, const VariableArrayType *VLA)
Strip off the variably-modified array types wrapping VLA and return the first element type that has a...
Definition ExprUtils.cpp:15
bool isTrivialFiller(const Expr *E)
Check whether E is a trivial array filler, that is, one that is equivalent to zero-initialization.
bool isCheapEnoughToEvaluateUnconditionally(const Expr *E, const ASTContext &Ctx)
Check whether E is cheap enough and side-effect-free enough to evaluate unconditionally instead of co...
Definition ExprUtils.cpp:87
bool isBlockVarRef(const Expr *E)
Check whether the value of E is possibly a reference to or into a __block variable.
Definition ExprUtils.cpp:24
bool onlyHasInlineBuiltinDeclaration(const FunctionDecl *FD)
Detect the unusual situation where an inline version of a builtin is shadowed by a non-inline version...
ConstantEmissionKind checkVarTypeForConstantEmission(QualType Type)
Can we constant-emit a load of a reference to a variable of the given type?
bool isConstantEmittableObjectType(QualType Type)
Given an object of the canonical type Type, can we safely copy a value out of it based on its initial...
ConstantEmissionKind
How a reference to a variable can be emitted as a constant.
Definition ExprUtils.h:54
bool isa(CodeGen::Address addr)
Definition Address.h:330