aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/Expr.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/AST/Expr.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'clang/lib/AST/Expr.cpp')
-rw-r--r--clang/lib/AST/Expr.cpp101
1 files changed, 93 insertions, 8 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index ca477e6500c5..67862a8692ac 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -37,6 +37,7 @@
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstring>
+#include <optional>
using namespace clang;
const Expr *Expr::getBestDynamicClassTypeExpr() const {
@@ -203,6 +204,88 @@ bool Expr::isKnownToHaveBooleanValue(bool Semantic) const {
return false;
}
+bool Expr::isFlexibleArrayMemberLike(
+ ASTContext &Context,
+ LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel,
+ bool IgnoreTemplateOrMacroSubstitution) const {
+
+ // For compatibility with existing code, we treat arrays of length 0 or
+ // 1 as flexible array members.
+ const auto *CAT = Context.getAsConstantArrayType(getType());
+ if (CAT) {
+ llvm::APInt Size = CAT->getSize();
+
+ using FAMKind = LangOptions::StrictFlexArraysLevelKind;
+
+ if (StrictFlexArraysLevel == FAMKind::IncompleteOnly)
+ return false;
+
+ // GCC extension, only allowed to represent a FAM.
+ if (Size == 0)
+ return true;
+
+ if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete && Size.uge(1))
+ return false;
+
+ if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete && Size.uge(2))
+ return false;
+ } else if (!Context.getAsIncompleteArrayType(getType()))
+ return false;
+
+ const Expr *E = IgnoreParens();
+
+ const NamedDecl *ND = nullptr;
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ ND = DRE->getDecl();
+ else if (const auto *ME = dyn_cast<MemberExpr>(E))
+ ND = ME->getMemberDecl();
+ else if (const auto *IRE = dyn_cast<ObjCIvarRefExpr>(E))
+ return IRE->getDecl()->getNextIvar() == nullptr;
+
+ if (!ND)
+ return false;
+
+ // A flexible array member must be the last member in the class.
+ // FIXME: If the base type of the member expr is not FD->getParent(),
+ // this should not be treated as a flexible array member access.
+ if (const auto *FD = dyn_cast<FieldDecl>(ND)) {
+ // GCC treats an array memeber of a union as an FAM if the size is one or
+ // zero.
+ if (CAT) {
+ llvm::APInt Size = CAT->getSize();
+ if (FD->getParent()->isUnion() && (Size.isZero() || Size.isOne()))
+ return true;
+ }
+
+ // Don't consider sizes resulting from macro expansions or template argument
+ // substitution to form C89 tail-padded arrays.
+ if (IgnoreTemplateOrMacroSubstitution) {
+ TypeSourceInfo *TInfo = FD->getTypeSourceInfo();
+ while (TInfo) {
+ TypeLoc TL = TInfo->getTypeLoc();
+ // Look through typedefs.
+ if (TypedefTypeLoc TTL = TL.getAsAdjusted<TypedefTypeLoc>()) {
+ const TypedefNameDecl *TDL = TTL.getTypedefNameDecl();
+ TInfo = TDL->getTypeSourceInfo();
+ continue;
+ }
+ if (ConstantArrayTypeLoc CTL = TL.getAs<ConstantArrayTypeLoc>()) {
+ const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr());
+ if (!SizeExpr || SizeExpr->getExprLoc().isMacroID())
+ return false;
+ }
+ break;
+ }
+ }
+
+ RecordDecl::field_iterator FI(
+ DeclContext::decl_iterator(const_cast<FieldDecl *>(FD)));
+ return ++FI == FD->getParent()->field_end();
+ }
+
+ return false;
+}
+
const ValueDecl *
Expr::getAsBuiltinConstantDeclRef(const ASTContext &Context) const {
Expr::EvalResult Eval;
@@ -277,7 +360,7 @@ ConstantExpr::getStorageKind(const APValue &Value) {
case APValue::Int:
if (!Value.getInt().needsCleanup())
return ConstantExpr::RSK_Int64;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
default:
return ConstantExpr::RSK_APValue;
}
@@ -562,10 +645,10 @@ std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context) const {
std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context,
QualType Ty) {
auto MangleCallback = [](ASTContext &Ctx,
- const NamedDecl *ND) -> llvm::Optional<unsigned> {
+ const NamedDecl *ND) -> std::optional<unsigned> {
if (const auto *RD = dyn_cast<CXXRecordDecl>(ND))
return RD->getDeviceLambdaManglingNumber();
- return llvm::None;
+ return std::nullopt;
};
std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
@@ -2633,7 +2716,7 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
}
// Fallthrough for generic call handling.
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
}
case CallExprClass:
case CXXMemberCallExprClass:
@@ -3562,6 +3645,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ShuffleVectorExprClass:
case ConvertVectorExprClass:
case AsTypeExprClass:
+ case CXXParenListInitExprClass:
// These have a side-effect if any subexpression does.
break;
@@ -3609,7 +3693,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
DCE->getCastKind() == CK_Dynamic)
return true;
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case ImplicitCastExprClass:
case CStyleCastExprClass:
case CXXStaticCastExprClass:
@@ -3857,7 +3941,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
if (getType().isNull())
return NPCK_NotNull;
- // C++11 nullptr_t is always a null pointer constant.
+ // C++11/C2x nullptr_t is always a null pointer constant.
if (getType()->isNullPtrType())
return NPCK_CXX11_nullptr;
@@ -4451,7 +4535,8 @@ DesignatedInitUpdateExpr::DesignatedInitUpdateExpr(const ASTContext &C,
OK_Ordinary) {
BaseAndUpdaterExprs[0] = baseExpr;
- InitListExpr *ILE = new (C) InitListExpr(C, lBraceLoc, None, rBraceLoc);
+ InitListExpr *ILE =
+ new (C) InitListExpr(C, lBraceLoc, std::nullopt, rBraceLoc);
ILE->setType(baseExpr->getType());
BaseAndUpdaterExprs[1] = ILE;
@@ -4831,7 +4916,7 @@ RecoveryExpr::RecoveryExpr(ASTContext &Ctx, QualType T, SourceLocation BeginLoc,
OK_Ordinary),
BeginLoc(BeginLoc), EndLoc(EndLoc), NumExprs(SubExprs.size()) {
assert(!T.isNull());
- assert(llvm::all_of(SubExprs, [](Expr* E) { return E != nullptr; }));
+ assert(!llvm::is_contained(SubExprs, nullptr));
llvm::copy(SubExprs, getTrailingObjects<Expr *>());
setDependence(computeDependence(this));