Skip to content

Commit 6cc8317

Browse files
committedAug 25, 2017
[IRGen] Evaluate constant static variables referenced through member
expressions C++ allows us to reference static variables through member expressions. Prior to this commit, non-integer static variables that were referenced using a member expression were always emitted using lvalue loads. The old behaviour introduced an inconsistency between regular uses of static variables and member expressions uses. For example, the following program compiled and linked successfully: struct Foo { constexpr static const char *name = "foo"; }; int main() { return Foo::name[0] == 'f'; } but this program failed to link because "Foo::name" wasn't found: struct Foo { constexpr static const char *name = "foo"; }; int main() { Foo f; return f.name[0] == 'f'; } This commit ensures that constant static variables referenced through member expressions are emitted in the same way as ordinary static variable references. rdar://33942261 Differential Revision: https://reviews.llvm.org/D36876 llvm-svn: 311772
1 parent bc3e993 commit 6cc8317

File tree

6 files changed

+171
-44
lines changed

6 files changed

+171
-44
lines changed
 

Diff for: ‎clang/lib/CodeGen/CGExpr.cpp

+24-3
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,25 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
13391339
return ConstantEmission::forValue(C);
13401340
}
13411341

1342+
static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CodeGenFunction &CGF,
1343+
const MemberExpr *ME) {
1344+
if (auto *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
1345+
// Try to emit static variable member expressions as DREs.
1346+
return DeclRefExpr::Create(
1347+
CGF.getContext(), NestedNameSpecifierLoc(), SourceLocation(), VD,
1348+
/*RefersToEnclosingVariableOrCapture=*/false, ME->getExprLoc(),
1349+
ME->getType(), ME->getValueKind());
1350+
}
1351+
return nullptr;
1352+
}
1353+
1354+
CodeGenFunction::ConstantEmission
1355+
CodeGenFunction::tryEmitAsConstant(const MemberExpr *ME) {
1356+
if (DeclRefExpr *DRE = tryToConvertMemberExprToDeclRefExpr(*this, ME))
1357+
return tryEmitAsConstant(DRE);
1358+
return ConstantEmission();
1359+
}
1360+
13421361
llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue,
13431362
SourceLocation Loc) {
13441363
return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),
@@ -3540,6 +3559,11 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
35403559
}
35413560

35423561
LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
3562+
if (DeclRefExpr *DRE = tryToConvertMemberExprToDeclRefExpr(*this, E)) {
3563+
EmitIgnoredExpr(E->getBase());
3564+
return EmitDeclRefLValue(DRE);
3565+
}
3566+
35433567
Expr *BaseExpr = E->getBase();
35443568
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
35453569
LValue BaseLV;
@@ -3566,9 +3590,6 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
35663590
return LV;
35673591
}
35683592

3569-
if (auto *VD = dyn_cast<VarDecl>(ND))
3570-
return EmitGlobalVarDeclLValue(*this, E, VD);
3571-
35723593
if (const auto *FD = dyn_cast<FunctionDecl>(ND))
35733594
return EmitFunctionDeclLValue(*this, E, FD);
35743595

Diff for: ‎clang/lib/CodeGen/CGExprAgg.cpp

+1-18
Original file line numberDiff line numberDiff line change
@@ -124,24 +124,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
124124
}
125125

126126
// l-values.
127-
void VisitDeclRefExpr(DeclRefExpr *E) {
128-
// For aggregates, we should always be able to emit the variable
129-
// as an l-value unless it's a reference. This is due to the fact
130-
// that we can't actually ever see a normal l2r conversion on an
131-
// aggregate in C++, and in C there's no language standard
132-
// actively preventing us from listing variables in the captures
133-
// list of a block.
134-
if (E->getDecl()->getType()->isReferenceType()) {
135-
if (CodeGenFunction::ConstantEmission result
136-
= CGF.tryEmitAsConstant(E)) {
137-
EmitFinalDestCopy(E->getType(), result.getReferenceLValue(CGF, E));
138-
return;
139-
}
140-
}
141-
142-
EmitAggLoadOfLValue(E);
143-
}
144-
127+
void VisitDeclRefExpr(DeclRefExpr *E) { EmitAggLoadOfLValue(E); }
145128
void VisitMemberExpr(MemberExpr *ME) { EmitAggLoadOfLValue(ME); }
146129
void VisitUnaryDeref(UnaryOperator *E) { EmitAggLoadOfLValue(E); }
147130
void VisitStringLiteral(StringLiteral *E) { EmitAggLoadOfLValue(E); }

Diff for: ‎clang/lib/CodeGen/CGExprComplex.cpp

+21-10
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,22 @@ class ComplexExprEmitter
120120
return Visit(E->getSubExpr());
121121
}
122122

123+
ComplexPairTy emitConstant(const CodeGenFunction::ConstantEmission &Constant,
124+
Expr *E) {
125+
assert(Constant && "not a constant");
126+
if (Constant.isReference())
127+
return EmitLoadOfLValue(Constant.getReferenceLValue(CGF, E),
128+
E->getExprLoc());
129+
130+
llvm::Constant *pair = Constant.getValue();
131+
return ComplexPairTy(pair->getAggregateElement(0U),
132+
pair->getAggregateElement(1U));
133+
}
123134

124135
// l-values.
125136
ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) {
126-
if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) {
127-
if (result.isReference())
128-
return EmitLoadOfLValue(result.getReferenceLValue(CGF, E),
129-
E->getExprLoc());
130-
131-
llvm::Constant *pair = result.getValue();
132-
return ComplexPairTy(pair->getAggregateElement(0U),
133-
pair->getAggregateElement(1U));
134-
}
137+
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
138+
return emitConstant(Constant, E);
135139
return EmitLoadOfLValue(E);
136140
}
137141
ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
@@ -141,7 +145,14 @@ class ComplexExprEmitter
141145
return CGF.EmitObjCMessageExpr(E).getComplexVal();
142146
}
143147
ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
144-
ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
148+
ComplexPairTy VisitMemberExpr(MemberExpr *ME) {
149+
if (CodeGenFunction::ConstantEmission Constant =
150+
CGF.tryEmitAsConstant(ME)) {
151+
CGF.EmitIgnoredExpr(ME->getBase());
152+
return emitConstant(Constant, ME);
153+
}
154+
return EmitLoadOfLValue(ME);
155+
}
145156
ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
146157
if (E->isGLValue())
147158
return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());

Diff for: ‎clang/lib/CodeGen/CGExprScalar.cpp

+20-13
Original file line numberDiff line numberDiff line change
@@ -428,14 +428,19 @@ class ScalarExprEmitter
428428
return CGF.getOpaqueRValueMapping(E).getScalarVal();
429429
}
430430

431+
Value *emitConstant(const CodeGenFunction::ConstantEmission &Constant,
432+
Expr *E) {
433+
assert(Constant && "not a constant");
434+
if (Constant.isReference())
435+
return EmitLoadOfLValue(Constant.getReferenceLValue(CGF, E),
436+
E->getExprLoc());
437+
return Constant.getValue();
438+
}
439+
431440
// l-values.
432441
Value *VisitDeclRefExpr(DeclRefExpr *E) {
433-
if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) {
434-
if (result.isReference())
435-
return EmitLoadOfLValue(result.getReferenceLValue(CGF, E),
436-
E->getExprLoc());
437-
return result.getValue();
438-
}
442+
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
443+
return emitConstant(Constant, E);
439444
return EmitLoadOfLValue(E);
440445
}
441446

@@ -1299,13 +1304,15 @@ Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
12991304
}
13001305

13011306
Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
1302-
llvm::APSInt Value;
1303-
if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) {
1304-
if (E->isArrow())
1305-
CGF.EmitScalarExpr(E->getBase());
1306-
else
1307-
EmitLValue(E->getBase());
1308-
return Builder.getInt(Value);
1307+
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E)) {
1308+
CGF.EmitIgnoredExpr(E->getBase());
1309+
return emitConstant(Constant, E);
1310+
} else {
1311+
llvm::APSInt Value;
1312+
if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) {
1313+
CGF.EmitIgnoredExpr(E->getBase());
1314+
return Builder.getInt(Value);
1315+
}
13091316
}
13101317

13111318
return EmitLoadOfLValue(E);

Diff for: ‎clang/lib/CodeGen/CodeGenFunction.h

+1
Original file line numberDiff line numberDiff line change
@@ -3161,6 +3161,7 @@ class CodeGenFunction : public CodeGenTypeCache {
31613161
};
31623162

31633163
ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr);
3164+
ConstantEmission tryEmitAsConstant(const MemberExpr *ME);
31643165

31653166
RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e,
31663167
AggValueSlot slot = AggValueSlot::ignored());
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
2+
3+
struct Agg { const char * x; const char * y; constexpr Agg() : x(0), y(0) {} };
4+
5+
struct Struct {
6+
constexpr static const char *name = "foo";
7+
8+
constexpr static __complex float complexValue = 42.0;
9+
10+
static constexpr const Agg &agg = Agg();
11+
12+
Struct();
13+
Struct(int x);
14+
};
15+
16+
void use(int n, const char *c);
17+
18+
Struct *getPtr();
19+
20+
// CHECK: @[[STR:.*]] = private unnamed_addr constant [4 x i8] c"foo\00", align 1
21+
22+
void scalarStaticVariableInMemberExpr(Struct *ptr, Struct &ref) {
23+
use(1, Struct::name);
24+
// CHECK: call void @_Z3useiPKc(i32 1, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
25+
Struct s;
26+
use(2, s.name);
27+
// CHECK: call void @_Z3useiPKc(i32 2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
28+
use(3, ptr->name);
29+
// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
30+
// CHECK: call void @_Z3useiPKc(i32 3, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
31+
use(4, ref.name);
32+
// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
33+
// CHECK: call void @_Z3useiPKc(i32 4, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
34+
use(5, Struct(2).name);
35+
// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
36+
// CHECK: call void @_Z3useiPKc(i32 5, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
37+
use(6, getPtr()->name);
38+
// CHECK: call %struct.Struct* @_Z6getPtrv()
39+
// CHECK: call void @_Z3useiPKc(i32 6, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
40+
}
41+
42+
void use(int n, __complex float v);
43+
44+
void complexStaticVariableInMemberExpr(Struct *ptr, Struct &ref) {
45+
use(1, Struct::complexValue);
46+
// CHECK: store float 4.200000e+01, float* %[[coerce0:.*]].{{.*}}, align 4
47+
// CHECK: store float 0.000000e+00, float* %[[coerce0]].{{.*}}, align 4
48+
// CHECK: %[[cast0:.*]] = bitcast { float, float }* %[[coerce0]] to <2 x float>*
49+
// CHECK: %[[vector0:.*]] = load <2 x float>, <2 x float>* %[[cast0]], align 4
50+
// CHECK: call void @_Z3useiCf(i32 1, <2 x float> %[[vector0]])
51+
Struct s;
52+
use(2, s.complexValue);
53+
// CHECK: store float 4.200000e+01, float* %[[coerce1:.*]].{{.*}}, align 4
54+
// CHECK: store float 0.000000e+00, float* %[[coerce1]].{{.*}}, align 4
55+
// CHECK: %[[cast1:.*]] = bitcast { float, float }* %[[coerce1]] to <2 x float>*
56+
// CHECK: %[[vector1:.*]] = load <2 x float>, <2 x float>* %[[cast1]], align 4
57+
// CHECK: call void @_Z3useiCf(i32 2, <2 x float> %[[vector1]])
58+
use(3, ptr->complexValue);
59+
// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
60+
// CHECK: store float 4.200000e+01, float* %[[coerce2:.*]].{{.*}}, align 4
61+
// CHECK: store float 0.000000e+00, float* %[[coerce2]].{{.*}}, align 4
62+
// CHECK: %[[cast2:.*]] = bitcast { float, float }* %[[coerce2]] to <2 x float>*
63+
// CHECK: %[[vector2:.*]] = load <2 x float>, <2 x float>* %[[cast2]], align 4
64+
// CHECK: call void @_Z3useiCf(i32 3, <2 x float> %[[vector2]])
65+
use(4, ref.complexValue);
66+
// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
67+
// CHECK: store float 4.200000e+01, float* %[[coerce3:.*]].{{.*}}, align 4
68+
// CHECK: store float 0.000000e+00, float* %[[coerce3]].{{.*}}, align 4
69+
// CHECK: %[[cast3:.*]] = bitcast { float, float }* %[[coerce3]] to <2 x float>*
70+
// CHECK: %[[vector3:.*]] = load <2 x float>, <2 x float>* %[[cast3]], align 4
71+
// CHECK: call void @_Z3useiCf(i32 4, <2 x float> %[[vector3]])
72+
use(5, Struct(2).complexValue);
73+
// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
74+
// CHECK: store float 4.200000e+01, float* %[[coerce4:.*]].{{.*}}, align 4
75+
// CHECK: store float 0.000000e+00, float* %[[coerce4]].{{.*}}, align 4
76+
// CHECK: %[[cast4:.*]] = bitcast { float, float }* %[[coerce4]] to <2 x float>*
77+
// CHECK: %[[vector4:.*]] = load <2 x float>, <2 x float>* %[[cast4]], align 4
78+
// CHECK: call void @_Z3useiCf(i32 5, <2 x float> %[[vector4]])
79+
use(6, getPtr()->complexValue);
80+
// CHECK: call %struct.Struct* @_Z6getPtrv()
81+
// CHECK: store float 4.200000e+01, float* %[[coerce5:.*]].{{.*}}, align 4
82+
// CHECK: store float 0.000000e+00, float* %[[coerce5]].{{.*}}, align 4
83+
// CHECK: %[[cast5:.*]] = bitcast { float, float }* %[[coerce5]] to <2 x float>*
84+
// CHECK: %[[vector5:.*]] = load <2 x float>, <2 x float>* %[[cast5]], align 4
85+
// CHECK: call void @_Z3useiCf(i32 6, <2 x float> %[[vector5]])
86+
}
87+
88+
void aggregateRefInMemberExpr(Struct *ptr, Struct &ref) {
89+
use(1, Struct::agg.x);
90+
// CHECK: %[[value0:.*]] = load i8*, i8** getelementptr inbounds (%struct.Agg, %struct.Agg* @_ZGRN6Struct3aggE_, i32 0, i32 0), align 8
91+
// CHECK: call void @_Z3useiPKc(i32 1, i8* %[[value0]])
92+
Struct s;
93+
use(2, s.agg.x);
94+
// CHECK: %[[value1:.*]] = load i8*, i8** getelementptr inbounds (%struct.Agg, %struct.Agg* @_ZGRN6Struct3aggE_, i32 0, i32 0), align 8
95+
// CHECK: call void @_Z3useiPKc(i32 2, i8* %[[value1]])
96+
use(3, ptr->agg.x);
97+
// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
98+
// CHECK: %[[value2:.*]] = load i8*, i8** getelementptr inbounds (%struct.Agg, %struct.Agg* @_ZGRN6Struct3aggE_, i32 0, i32 0), align 8
99+
// CHECK: call void @_Z3useiPKc(i32 3, i8* %[[value2]])
100+
use(4, ref.agg.x);
101+
// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
102+
// CHECK: %[[value3:.*]] = load i8*, i8** getelementptr inbounds (%struct.Agg, %struct.Agg* @_ZGRN6Struct3aggE_, i32 0, i32 0), align 8
103+
// CHECK: call void @_Z3useiPKc(i32 4, i8* %[[value3]])
104+
}

0 commit comments

Comments
 (0)
Please sign in to comment.