Skip to content

Commit 6f22687

Browse files
author
git apple-llvm automerger
committed
Merge commit 'ff54c191d6f9' from apple/main into swift/next
2 parents 07ae7d6 + ff54c19 commit 6f22687

File tree

5 files changed

+36
-29
lines changed

5 files changed

+36
-29
lines changed

clang/lib/AST/Decl.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2280,7 +2280,9 @@ void VarDecl::setInit(Expr *I) {
22802280
bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const {
22812281
const LangOptions &Lang = C.getLangOpts();
22822282

2283-
if (!Lang.CPlusPlus)
2283+
// OpenCL permits const integral variables to be used in constant
2284+
// expressions, like in C++98.
2285+
if (!Lang.CPlusPlus && !Lang.OpenCL)
22842286
return false;
22852287

22862288
// Function parameters are never usable in constant expressions.
@@ -2299,7 +2301,7 @@ bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const {
22992301
// Only const objects can be used in constant expressions in C++. C++98 does
23002302
// not require the variable to be non-volatile, but we consider this to be a
23012303
// defect.
2302-
if (!getType().isConstQualified() || getType().isVolatileQualified())
2304+
if (!getType().isConstant(C) || getType().isVolatileQualified())
23032305
return false;
23042306

23052307
// In C++, const, non-volatile variables of integral or enumeration types
@@ -2325,14 +2327,14 @@ bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const {
23252327
if (!DefVD->mightBeUsableInConstantExpressions(Context))
23262328
return false;
23272329
// ... and its initializer is a constant initializer.
2328-
if (!DefVD->hasConstantInitialization())
2330+
if (Context.getLangOpts().CPlusPlus && !DefVD->hasConstantInitialization())
23292331
return false;
23302332
// C++98 [expr.const]p1:
23312333
// An integral constant-expression can involve only [...] const variables
23322334
// or static data members of integral or enumeration types initialized with
23332335
// [integer] constant expressions (dcl.init)
2334-
if (Context.getLangOpts().CPlusPlus && !Context.getLangOpts().CPlusPlus11 &&
2335-
!DefVD->hasICEInitializer(Context))
2336+
if ((Context.getLangOpts().CPlusPlus || Context.getLangOpts().OpenCL) &&
2337+
!Context.getLangOpts().CPlusPlus11 && !DefVD->hasICEInitializer(Context))
23362338
return false;
23372339
return true;
23382340
}

clang/lib/AST/ExprConstant.cpp

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3298,10 +3298,10 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
32983298
// FIXME: We don't diagnose cases that aren't potentially usable in constant
32993299
// expressions here; doing so would regress diagnostics for things like
33003300
// reading from a volatile constexpr variable.
3301-
if ((!VD->hasConstantInitialization() &&
3301+
if ((Info.getLangOpts().CPlusPlus && !VD->hasConstantInitialization() &&
33023302
VD->mightBeUsableInConstantExpressions(Info.Ctx)) ||
3303-
(Info.getLangOpts().CPlusPlus && !Info.getLangOpts().CPlusPlus11 &&
3304-
!VD->hasICEInitializer(Info.Ctx))) {
3303+
((Info.getLangOpts().CPlusPlus || Info.getLangOpts().OpenCL) &&
3304+
!Info.getLangOpts().CPlusPlus11 && !VD->hasICEInitializer(Info.Ctx))) {
33053305
Info.CCEDiag(E, diag::note_constexpr_var_init_non_constant, 1) << VD;
33063306
NoteLValueLocation(Info, Base);
33073307
}
@@ -4011,10 +4011,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
40114011
return CompleteObject();
40124012
}
40134013

4014-
// In OpenCL if a variable is in constant address space it is a const value.
4015-
bool IsConstant = BaseType.isConstQualified() ||
4016-
(Info.getLangOpts().OpenCL &&
4017-
BaseType.getAddressSpace() == LangAS::opencl_constant);
4014+
bool IsConstant = BaseType.isConstant(Info.Ctx);
40184015

40194016
// Unless we're looking at a local variable or argument in a constexpr call,
40204017
// the variable we're reading must be const.
@@ -4035,8 +4032,6 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
40354032
} else if (VD->isConstexpr()) {
40364033
// OK, we can read this variable.
40374034
} else if (BaseType->isIntegralOrEnumerationType()) {
4038-
// In OpenCL if a variable is in constant address space it is a const
4039-
// value.
40404035
if (!IsConstant) {
40414036
if (!IsAccess)
40424037
return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
@@ -14863,7 +14858,6 @@ bool Expr::EvalResult::isGlobalLValue() const {
1486314858
return IsGlobalLValue(Val.getLValueBase());
1486414859
}
1486514860

14866-
1486714861
/// isIntegerConstantExpr - this recursive routine will test if an expression is
1486814862
/// an integer constant expression.
1486914863

@@ -15066,15 +15060,20 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
1506615060
return CheckICE(cast<CXXRewrittenBinaryOperator>(E)->getSemanticForm(),
1506715061
Ctx);
1506815062
case Expr::DeclRefExprClass: {
15069-
if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
15063+
const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();
15064+
if (isa<EnumConstantDecl>(D))
1507015065
return NoDiag();
15071-
const VarDecl *VD = dyn_cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
15072-
if (VD && VD->isUsableInConstantExpressions(Ctx)) {
15073-
// C++ 7.1.5.1p2
15074-
// A variable of non-volatile const-qualified integral or enumeration
15075-
// type initialized by an ICE can be used in ICEs.
15066+
15067+
// C++ and OpenCL (FIXME: spec reference?) allow reading const-qualified
15068+
// integer variables in constant expressions:
15069+
//
15070+
// C++ 7.1.5.1p2
15071+
// A variable of non-volatile const-qualified integral or enumeration
15072+
// type initialized by an ICE can be used in ICEs.
15073+
const VarDecl *VD = dyn_cast<VarDecl>(D);
15074+
if (VD && VD->isUsableInConstantExpressions(Ctx))
1507615075
return NoDiag();
15077-
}
15076+
1507815077
return ICEDiag(IK_NotICE, E->getBeginLoc());
1507915078
}
1508015079
case Expr::UnaryOperatorClass: {

clang/lib/Sema/SemaType.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,9 +2259,8 @@ static ExprResult checkArraySize(Sema &S, Expr *&ArraySize,
22592259
}
22602260
} Diagnoser(VLADiag, VLAIsError);
22612261

2262-
ExprResult R = S.VerifyIntegerConstantExpression(
2263-
ArraySize, &SizeVal, Diagnoser,
2264-
S.LangOpts.OpenCL ? Sema::AllowFold : Sema::NoFold);
2262+
ExprResult R =
2263+
S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser);
22652264
if (Diagnoser.IsVLA)
22662265
return ExprResult();
22672266
return R;

clang/test/CodeGenOpenCL/amdgpu-nullptr.cl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ int fold_int5_local = (int) &((local StructTy1*)0)->p2;
104104
// NOOPT: @test_static_var_private.sp2 = internal addrspace(1) global i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), align 4
105105
// NOOPT: @test_static_var_private.sp3 = internal addrspace(1) global i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), align 4
106106
// NOOPT: @test_static_var_private.sp4 = internal addrspace(1) global i8 addrspace(5)* null, align 4
107-
// NOOPT: @test_static_var_private.sp5 = internal addrspace(1) global i8 addrspace(5)* null, align 4
107+
// NOOPT: @test_static_var_private.sp5 = internal addrspace(1) global i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), align 4
108108
// NOOPT: @test_static_var_private.SS1 = internal addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8
109109
// NOOPT: @test_static_var_private.SS2 = internal addrspace(1) global %struct.StructTy2 zeroinitializer, align 8
110110

@@ -123,7 +123,7 @@ void test_static_var_private(void) {
123123
// NOOPT: @test_static_var_local.sp2 = internal addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4
124124
// NOOPT: @test_static_var_local.sp3 = internal addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4
125125
// NOOPT: @test_static_var_local.sp4 = internal addrspace(1) global i8 addrspace(3)* null, align 4
126-
// NOOPT: @test_static_var_local.sp5 = internal addrspace(1) global i8 addrspace(3)* null, align 4
126+
// NOOPT: @test_static_var_local.sp5 = internal addrspace(1) global i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), align 4
127127
// NOOPT: @test_static_var_local.SS1 = internal addrspace(1) global %struct.StructTy1 { i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(4)* null, i8 addrspace(1)* null, i8* null }, align 8
128128
// NOOPT: @test_static_var_local.SS2 = internal addrspace(1) global %struct.StructTy2 zeroinitializer, align 8
129129
void test_static_var_local(void) {
@@ -142,7 +142,7 @@ void test_static_var_local(void) {
142142
// NOOPT: store i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(5)* addrspace(5)* %sp1, align 4
143143
// NOOPT: store i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(5)* addrspace(5)* %sp2, align 4
144144
// NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp3, align 4
145-
// NOOPT: store i8 addrspace(5)* null, i8 addrspace(5)* addrspace(5)* %sp4, align 4
145+
// NOOPT: store i8 addrspace(5)* addrspacecast (i8* null to i8 addrspace(5)*), i8 addrspace(5)* addrspace(5)* %sp4, align 4
146146
// NOOPT: %[[SS1:.*]] = bitcast %struct.StructTy1 addrspace(5)* %SS1 to i8 addrspace(5)*
147147
// NOOPT: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 8 %[[SS1]], i8 addrspace(4)* align 8 bitcast (%struct.StructTy1 addrspace(4)* @__const.test_func_scope_var_private.SS1 to i8 addrspace(4)*), i64 32, i1 false)
148148
// NOOPT: %[[SS2:.*]] = bitcast %struct.StructTy2 addrspace(5)* %SS2 to i8 addrspace(5)*
@@ -162,7 +162,7 @@ void test_func_scope_var_private(void) {
162162
// NOOPT: store i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(3)* addrspace(5)* %sp1, align 4
163163
// NOOPT: store i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(3)* addrspace(5)* %sp2, align 4
164164
// NOOPT: store i8 addrspace(3)* null, i8 addrspace(3)* addrspace(5)* %sp3, align 4
165-
// NOOPT: store i8 addrspace(3)* null, i8 addrspace(3)* addrspace(5)* %sp4, align 4
165+
// NOOPT: store i8 addrspace(3)* addrspacecast (i8* null to i8 addrspace(3)*), i8 addrspace(3)* addrspace(5)* %sp4, align 4
166166
// NOOPT: %[[SS1:.*]] = bitcast %struct.StructTy1 addrspace(5)* %SS1 to i8 addrspace(5)*
167167
// NOOPT: call void @llvm.memcpy.p5i8.p4i8.i64(i8 addrspace(5)* align 8 %[[SS1]], i8 addrspace(4)* align 8 bitcast (%struct.StructTy1 addrspace(4)* @__const.test_func_scope_var_local.SS1 to i8 addrspace(4)*), i64 32, i1 false)
168168
// NOOPT: %[[SS2:.*]] = bitcast %struct.StructTy2 addrspace(5)* %SS2 to i8 addrspace(5)*

clang/test/SemaOpenCL/address-spaces.cl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
__constant int ci = 1;
66

7+
// __constant ints are allowed in constant expressions.
8+
enum use_ci_in_enum { enumerator = ci };
9+
typedef int use_ci_in_array_bound[ci];
10+
11+
// general constant folding of array bounds is not permitted
12+
typedef int folding_in_array_bounds[&ci + 3 - &ci]; // expected-error-re {{{{variable length arrays are not supported in OpenCL|array size is not a constant expression}}}} expected-note {{cannot refer to element 3}}
13+
714
__kernel void foo(__global int *gip) {
815
__local int li;
916
__local int lj = 2; // expected-error {{'__local' variable cannot have an initializer}}

0 commit comments

Comments
 (0)