diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/AST/Expr.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'clang/lib/AST/Expr.cpp')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 101 |
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)); |