aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r--clang/lib/AST/ExprConstant.cpp103
1 files changed, 71 insertions, 32 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 34af9cc..5cf2b9a 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -401,7 +401,7 @@ namespace {
assert(!Invalid && "invalid designator has no subobject type");
return MostDerivedPathLength == Entries.size()
? MostDerivedType
- : Ctx.getRecordType(getAsBaseClass(Entries.back()));
+ : Ctx.getCanonicalTagType(getAsBaseClass(Entries.back()));
}
/// Update this designator to refer to the first element within this array.
@@ -2623,7 +2623,8 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
Value.getUnionValue(), Kind, Value.getUnionField(), CheckedTemps);
}
if (Value.isStruct()) {
- RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
+ RecordDecl *RD =
+ Type->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {
unsigned BaseIndex = 0;
for (const CXXBaseSpecifier &BS : CD->bases()) {
@@ -4109,7 +4110,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
}
// Next subobject is a class, struct or union field.
- RecordDecl *RD = ObjType->castAs<RecordType>()->getDecl();
+ RecordDecl *RD = ObjType->castAs<RecordType>()->getOriginalDecl();
if (RD->isUnion()) {
const FieldDecl *UnionField = O->getUnionField();
if (!UnionField ||
@@ -4144,7 +4145,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
const CXXRecordDecl *Base = getAsBaseClass(Sub.Entries[I]);
O = &O->getStructBase(getBaseIndex(Derived, Base));
- ObjType = getSubobjectType(ObjType, Info.Ctx.getRecordType(Base));
+ ObjType = getSubobjectType(ObjType, Info.Ctx.getCanonicalTagType(Base));
}
}
}
@@ -6363,7 +6364,7 @@ static bool HandleDynamicCast(EvalInfo &Info, const ExplicitCastExpr *E,
const CXXRecordDecl *C = E->getTypeAsWritten()->getPointeeCXXRecordDecl();
assert(C && "dynamic_cast target is not void pointer nor class");
- CanQualType CQT = Info.Ctx.getCanonicalType(Info.Ctx.getRecordType(C));
+ CanQualType CQT = Info.Ctx.getCanonicalTagType(C);
auto RuntimeCheckFailed = [&] (CXXBasePaths *Paths) {
// C++ [expr.dynamic.cast]p9:
@@ -6389,7 +6390,7 @@ static bool HandleDynamicCast(EvalInfo &Info, const ExplicitCastExpr *E,
}
Info.FFDiag(E, diag::note_constexpr_dynamic_cast_to_reference_failed)
<< DiagKind << Ptr.Designator.getType(Info.Ctx)
- << Info.Ctx.getRecordType(DynType->Type)
+ << Info.Ctx.getCanonicalTagType(DynType->Type)
<< E->getType().getUnqualifiedType();
return false;
};
@@ -6886,8 +6887,8 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
// FIXME: This immediately starts the lifetime of all members of
// an anonymous struct. It would be preferable to strictly start
// member lifetime in initialization order.
- Success &=
- handleDefaultInitValue(Info.Ctx.getRecordType(CD), *Value);
+ Success &= handleDefaultInitValue(Info.Ctx.getCanonicalTagType(CD),
+ *Value);
}
// Store Subobject as its parent before updating it for the last element
// in the chain.
@@ -7794,7 +7795,8 @@ class BufferToAPValueConverter {
}
std::optional<APValue> visit(const EnumType *Ty, CharUnits Offset) {
- QualType RepresentationType = Ty->getDecl()->getIntegerType();
+ QualType RepresentationType =
+ Ty->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType();
assert(!RepresentationType.isNull() &&
"enum forward decl should be caught by Sema");
const auto *AsBuiltin =
@@ -8528,7 +8530,7 @@ public:
if (auto *DD = dyn_cast<CXXDestructorDecl>(FD)) {
assert(This && "no 'this' pointer for destructor call");
return HandleDestruction(Info, E, *This,
- Info.Ctx.getRecordType(DD->getParent())) &&
+ Info.Ctx.getCanonicalTagType(DD->getParent())) &&
CallScope.destroy();
}
@@ -8589,8 +8591,10 @@ public:
const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
if (!FD) return Error(E);
assert(!FD->getType()->isReferenceType() && "prvalue reference?");
- assert(BaseTy->castAs<RecordType>()->getDecl()->getCanonicalDecl() ==
- FD->getParent()->getCanonicalDecl() && "record / field mismatch");
+ assert(
+ BaseTy->castAs<RecordType>()->getOriginalDecl()->getCanonicalDecl() ==
+ FD->getParent()->getCanonicalDecl() &&
+ "record / field mismatch");
// Note: there is no lvalue base here. But this case should only ever
// happen in C or in C++98, where we cannot be evaluating a constexpr
@@ -8817,8 +8821,10 @@ public:
const ValueDecl *MD = E->getMemberDecl();
if (const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) {
- assert(BaseTy->castAs<RecordType>()->getDecl()->getCanonicalDecl() ==
- FD->getParent()->getCanonicalDecl() && "record / field mismatch");
+ assert(
+ BaseTy->castAs<RecordType>()->getOriginalDecl()->getCanonicalDecl() ==
+ FD->getParent()->getCanonicalDecl() &&
+ "record / field mismatch");
(void)BaseTy;
if (!HandleLValueMember(this->Info, E, Result, FD))
return false;
@@ -9257,8 +9263,8 @@ bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
if (!DynType)
return false;
- TypeInfo =
- TypeInfoLValue(Info.Ctx.getRecordType(DynType->Type).getTypePtr());
+ TypeInfo = TypeInfoLValue(
+ Info.Ctx.getCanonicalTagType(DynType->Type).getTypePtr());
}
return Success(APValue::LValueBase::getTypeInfo(TypeInfo, E->getType()));
@@ -9860,11 +9866,15 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
if (Value.isInt()) {
unsigned Size = Info.Ctx.getTypeSize(E->getType());
uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue();
- Result.Base = (Expr*)nullptr;
- Result.InvalidBase = false;
- Result.Offset = CharUnits::fromQuantity(N);
- Result.Designator.setInvalid();
- Result.IsNullPtr = false;
+ if (N == Info.Ctx.getTargetNullPointerValue(E->getType())) {
+ Result.setNull(Info.Ctx, E->getType());
+ } else {
+ Result.Base = (Expr *)nullptr;
+ Result.InvalidBase = false;
+ Result.Offset = CharUnits::fromQuantity(N);
+ Result.Designator.setInvalid();
+ Result.IsNullPtr = false;
+ }
return true;
} else {
// In rare instances, the value isn't an lvalue.
@@ -10814,7 +10824,8 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E,
}
bool RecordExprEvaluator::ZeroInitialization(const Expr *E, QualType T) {
- const RecordDecl *RD = T->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD =
+ T->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isInvalidDecl()) return false;
if (RD->isUnion()) {
// C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
@@ -10883,8 +10894,10 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
const Expr *ExprToVisit, ArrayRef<Expr *> Args) {
- const RecordDecl *RD =
- ExprToVisit->getType()->castAs<RecordType>()->getDecl();
+ const RecordDecl *RD = ExprToVisit->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
if (RD->isInvalidDecl()) return false;
const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD);
auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
@@ -11112,7 +11125,10 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
Result = APValue(APValue::UninitStruct(), 0, 2);
Array.moveInto(Result.getStructField(0));
- RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl *Record = E->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
RecordDecl::field_iterator Field = Record->field_begin();
assert(Field != Record->field_end() &&
Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
@@ -11624,7 +11640,13 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
case Builtin::BI__builtin_elementwise_add_sat:
- case Builtin::BI__builtin_elementwise_sub_sat: {
+ case Builtin::BI__builtin_elementwise_sub_sat:
+ case clang::X86::BI__builtin_ia32_pmulhuw128:
+ case clang::X86::BI__builtin_ia32_pmulhuw256:
+ case clang::X86::BI__builtin_ia32_pmulhuw512:
+ case clang::X86::BI__builtin_ia32_pmulhw128:
+ case clang::X86::BI__builtin_ia32_pmulhw256:
+ case clang::X86::BI__builtin_ia32_pmulhw512: {
APValue SourceLHS, SourceRHS;
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
@@ -11649,6 +11671,18 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
APSInt(LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS),
DestEltTy->isUnsignedIntegerOrEnumerationType())));
break;
+ case clang::X86::BI__builtin_ia32_pmulhuw128:
+ case clang::X86::BI__builtin_ia32_pmulhuw256:
+ case clang::X86::BI__builtin_ia32_pmulhuw512:
+ ResultElements.push_back(APValue(APSInt(llvm::APIntOps::mulhu(LHS, RHS),
+ /*isUnsigned=*/true)));
+ break;
+ case clang::X86::BI__builtin_ia32_pmulhw128:
+ case clang::X86::BI__builtin_ia32_pmulhw256:
+ case clang::X86::BI__builtin_ia32_pmulhw512:
+ ResultElements.push_back(APValue(APSInt(llvm::APIntOps::mulhs(LHS, RHS),
+ /*isUnsigned=*/false)));
+ break;
}
}
@@ -12885,7 +12919,10 @@ static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int,
static void addFlexibleArrayMemberInitSize(EvalInfo &Info, const QualType &T,
const LValue &LV, CharUnits &Size) {
if (!T.isNull() && T->isStructureType() &&
- T->getAsStructureType()->getDecl()->hasFlexibleArrayMember())
+ T->getAsStructureType()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->hasFlexibleArrayMember())
if (const auto *V = LV.getLValueBase().dyn_cast<const ValueDecl *>())
if (const auto *VD = dyn_cast<VarDecl>(V))
if (VD->hasInit())
@@ -15132,7 +15169,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
const RecordType *RT = CurrentType->getAs<RecordType>();
if (!RT)
return Error(OOE);
- RecordDecl *RD = RT->getDecl();
+ RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isInvalidDecl()) return false;
const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
unsigned i = MemberDecl->getFieldIndex();
@@ -15154,7 +15191,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
const RecordType *RT = CurrentType->getAs<RecordType>();
if (!RT)
return Error(OOE);
- RecordDecl *RD = RT->getDecl();
+ RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
if (RD->isInvalidDecl()) return false;
const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
@@ -15165,7 +15202,8 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
return Error(OOE);
// Add the offset to the base.
- Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
+ Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(
+ BaseRT->getOriginalDecl()->getDefinitionOrSelf()));
break;
}
}
@@ -15344,7 +15382,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
if (Info.Ctx.getLangOpts().CPlusPlus && DestType->isEnumeralType()) {
const EnumType *ET = dyn_cast<EnumType>(DestType.getCanonicalType());
- const EnumDecl *ED = ET->getDecl();
+ const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf();
// Check that the value is within the range of the enumeration values.
//
// This corressponds to [expr.static.cast]p10 which says:
@@ -18006,7 +18044,8 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
// Fabricate an arbitrary expression on the stack and pretend that it
// is a temporary being used as the 'this' pointer.
LValue This;
- ImplicitValueInitExpr VIE(RD ? Info.Ctx.getRecordType(RD) : Info.Ctx.IntTy);
+ ImplicitValueInitExpr VIE(RD ? Info.Ctx.getCanonicalTagType(RD)
+ : Info.Ctx.IntTy);
This.set({&VIE, Info.CurrentCall->Index});
ArrayRef<const Expr*> Args;