EvalInfo &Info, SourceLocation DiagLoc,
QualType Type, const APValue &Value,
ConstantExprKind Kind,
- SourceLocation SubobjectLoc,
+ const FieldDecl *SubobjectDecl,
CheckedTemporaries &CheckedTemps);
/// Check that this reference or pointer core constant expression is a valid
APValue *V = MTE->getOrCreateValue(false);
assert(V && "evasluation result refers to uninitialised temporary");
if (!CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression,
- Info, MTE->getExprLoc(), TempType, *V,
- Kind, SourceLocation(), CheckedTemps))
+ Info, MTE->getExprLoc(), TempType, *V, Kind,
+ /*SubobjectDecl=*/nullptr, CheckedTemps))
return false;
}
}
EvalInfo &Info, SourceLocation DiagLoc,
QualType Type, const APValue &Value,
ConstantExprKind Kind,
- SourceLocation SubobjectLoc,
+ const FieldDecl *SubobjectDecl,
CheckedTemporaries &CheckedTemps) {
if (!Value.hasValue()) {
- Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized)
- << true << Type;
- if (SubobjectLoc.isValid())
- Info.Note(SubobjectLoc, diag::note_constexpr_subobject_declared_here);
+ assert(SubobjectDecl && "SubobjectDecl shall be non-null");
+ Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) << SubobjectDecl;
+ Info.Note(SubobjectDecl->getLocation(),
+ diag::note_constexpr_subobject_declared_here);
return false;
}
for (unsigned I = 0, N = Value.getArrayInitializedElts(); I != N; ++I) {
if (!CheckEvaluationResult(CERK, Info, DiagLoc, EltTy,
Value.getArrayInitializedElt(I), Kind,
- SubobjectLoc, CheckedTemps))
+ SubobjectDecl, CheckedTemps))
return false;
}
if (!Value.hasArrayFiller())
return true;
return CheckEvaluationResult(CERK, Info, DiagLoc, EltTy,
- Value.getArrayFiller(), Kind, SubobjectLoc,
+ Value.getArrayFiller(), Kind, SubobjectDecl,
CheckedTemps);
}
if (Value.isUnion() && Value.getUnionField()) {
return CheckEvaluationResult(
CERK, Info, DiagLoc, Value.getUnionField()->getType(),
- Value.getUnionValue(), Kind, Value.getUnionField()->getLocation(),
- CheckedTemps);
+ Value.getUnionValue(), Kind, Value.getUnionField(), CheckedTemps);
}
if (Value.isStruct()) {
RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
for (const CXXBaseSpecifier &BS : CD->bases()) {
if (!CheckEvaluationResult(CERK, Info, DiagLoc, BS.getType(),
Value.getStructBase(BaseIndex), Kind,
- BS.getBeginLoc(), CheckedTemps))
+ /*SubobjectDecl=*/nullptr, CheckedTemps))
return false;
++BaseIndex;
}
continue;
if (!CheckEvaluationResult(CERK, Info, DiagLoc, I->getType(),
- Value.getStructField(I->getFieldIndex()),
- Kind, I->getLocation(), CheckedTemps))
+ Value.getStructField(I->getFieldIndex()), Kind,
+ I, CheckedTemps))
return false;
}
}
CheckedTemporaries CheckedTemps;
return CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression,
Info, DiagLoc, Type, Value, Kind,
- SourceLocation(), CheckedTemps);
+ /*SubobjectDecl=*/nullptr, CheckedTemps);
}
/// Check that this evaluated value is fully-initialized and can be loaded by
CheckedTemporaries CheckedTemps;
return CheckEvaluationResult(
CheckEvaluationResultKind::FullyInitialized, Info, DiagLoc, Type, Value,
- ConstantExprKind::Normal, SourceLocation(), CheckedTemps);
+ ConstantExprKind::Normal, /*SubobjectDecl=*/nullptr, CheckedTemps);
}
/// Enforce C++2a [expr.const]/4.17, which disallows new-expressions unless
}
static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI,
- QualType SubObjType,
- SourceLocation SubObjLoc) {
- S.FFDiag(SI, diag::note_constexpr_uninitialized) << true << SubObjType;
- if (SubObjLoc.isValid())
- S.Note(SubObjLoc, diag::note_constexpr_subobject_declared_here);
+ const FieldDecl *SubObjDecl) {
+ assert(SubObjDecl && "Subobject declaration does not exist");
+ S.FFDiag(SI, diag::note_constexpr_uninitialized) << SubObjDecl;
+ S.Note(SubObjDecl->getLocation(),
+ diag::note_constexpr_subobject_declared_here);
}
static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
} else {
for (size_t I = 0; I != NumElems; ++I) {
if (!BasePtr.atIndex(I).isInitialized()) {
- DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), ElemType,
- BasePtr.getFieldDesc()->getLocation());
+ DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC),
+ BasePtr.getField());
Result = false;
}
}
cast<ConstantArrayType>(FieldType->getAsArrayTypeUnsafe());
Result &= CheckArrayInitialized(S, OpPC, FieldPtr, CAT);
} else if (!FieldPtr.isInitialized()) {
- DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC),
- F.Decl->getType(), F.Decl->getLocation());
+ DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), F.Decl);
Result = false;
}
}
constexpr A() {}
};
constexpr A a; // expected-error {{must be initialized by a constant expression}} \
- // expected-note {{subobject of type 'int' is not initialized}} \
+ // expected-note {{subobject 'a' is not initialized}} \
// ref-error {{must be initialized by a constant expression}} \
- // ref-note {{subobject of type 'int' is not initialized}}
+ // ref-note {{subobject 'a' is not initialized}}
class Base {
constexpr Derived() : Base() {} };
constexpr Derived D; // expected-error {{must be initialized by a constant expression}} \
- // expected-note {{subobject of type 'int' is not initialized}} \
+ // expected-note {{subobject 'a' is not initialized}} \
// ref-error {{must be initialized by a constant expression}} \
- // ref-note {{subobject of type 'int' is not initialized}}
+ // ref-note {{subobject 'a' is not initialized}}
class C2 {
public:
A a;
constexpr C2() {} };
constexpr C2 c2; // expected-error {{must be initialized by a constant expression}} \
- // expected-note {{subobject of type 'int' is not initialized}} \
+ // expected-note {{subobject 'a' is not initialized}} \
// ref-error {{must be initialized by a constant expression}} \
- // ref-note {{subobject of type 'int' is not initialized}}
+ // ref-note {{subobject 'a' is not initialized}}
// FIXME: These two are currently disabled because the array fields
b.a.x = 2;
return b;
}
- constexpr B uninit = return_uninit(); // expected-error {{constant expression}} expected-note {{subobject of type 'int' is not initialized}}
+ constexpr B uninit = return_uninit(); // expected-error {{constant expression}} expected-note {{subobject 'y' is not initialized}}
static_assert(return_uninit().a.x == 2);
constexpr A return_uninit_struct() {
B b = {.b = 1};
b.a.x = 2;
- return b.a; // expected-note {{in call to 'A(b.a)'}} expected-note {{subobject of type 'int' is not initialized}}
+ return b.a; // expected-note {{in call to 'A(b.a)'}} expected-note {{subobject 'y' is not initialized}}
}
// Note that this is rejected even though return_uninit() is accepted, and
// return_uninit() copies the same stuff wrapped in a union.
}
};
constinit X x1(true);
- constinit X x2(false); // expected-error {{constant initializer}} expected-note {{constinit}} expected-note {{subobject of type 'int' is not initialized}}
+ constinit X x2(false); // expected-error {{constant initializer}} expected-note {{constinit}} expected-note {{subobject 'n' is not initialized}}
struct Y {
struct Z { int n; }; // expected-note {{here}}
};
// FIXME: This is working around clang not implementing DR2026. With that
// fixed, we should be able to test this without the injected copy.
- constexpr Y copy(Y y) { return y; } // expected-note {{in call to 'Y(y)'}} expected-note {{subobject of type 'int' is not initialized}}
+ constexpr Y copy(Y y) { return y; } // expected-note {{in call to 'Y(y)'}} expected-note {{subobject 'n' is not initialized}}
constexpr Y y1 = copy(Y());
static_assert(y1.z1.n == 1 && y1.z2.n == 2 && y1.z3.n == 3);