diff options
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 20 | ||||
-rw-r--r-- | clang/lib/AST/ASTStructuralEquivalence.cpp | 70 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Compiler.cpp | 43 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Interp.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Interp.h | 15 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/InterpBuiltin.cpp | 28 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/InterpStack.h | 2 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Pointer.cpp | 26 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Pointer.h | 10 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Program.cpp | 6 | ||||
-rw-r--r-- | clang/lib/AST/ByteCode/Program.h | 3 | ||||
-rw-r--r-- | clang/lib/AST/Expr.cpp | 23 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 6 | ||||
-rw-r--r-- | clang/lib/AST/ExprObjC.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/OSLog.cpp | 18 | ||||
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 2 |
16 files changed, 179 insertions, 96 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 6b6275f..16cf114 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -940,7 +940,6 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize), DependentTypeOfExprTypes(this_()), DependentDecltypeTypes(this_()), DependentPackIndexingTypes(this_()), TemplateSpecializationTypes(this_()), - DependentTemplateSpecializationTypes(this_()), DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()), DeducedTemplates(this_()), ArrayParameterTypes(this_()), CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts), @@ -5979,10 +5978,9 @@ QualType ASTContext::getDependentTemplateSpecializationType( llvm::FoldingSetNodeID ID; DependentTemplateSpecializationType::Profile(ID, *this, Keyword, Name, Args); - void *InsertPos = nullptr; - if (auto *T = DependentTemplateSpecializationTypes.FindNodeOrInsertPos( - ID, InsertPos)) - return QualType(T, 0); + if (auto const T_iter = DependentTemplateSpecializationTypes.find(ID); + T_iter != DependentTemplateSpecializationTypes.end()) + return QualType(T_iter->getSecond(), 0); NestedNameSpecifier *NNS = Name.getQualifier(); @@ -6001,11 +5999,6 @@ QualType ASTContext::getDependentTemplateSpecializationType( CanonKeyword, {CanonNNS, Name.getName(), /*HasTemplateKeyword=*/true}, CanonArgs, /*IsCanonical=*/true); - // Find the insert position again. - [[maybe_unused]] auto *Nothing = - DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, - InsertPos); - assert(!Nothing && "canonical type broken"); } } else { assert(Keyword == getCanonicalElaboratedTypeKeyword(Keyword)); @@ -6021,8 +6014,13 @@ QualType ASTContext::getDependentTemplateSpecializationType( alignof(DependentTemplateSpecializationType)); auto *T = new (Mem) DependentTemplateSpecializationType(Keyword, Name, Args, Canon); +#ifndef NDEBUG + llvm::FoldingSetNodeID InsertedID; + T->Profile(InsertedID, *this); + assert(InsertedID == ID && "ID does not match"); +#endif Types.push_back(T); - DependentTemplateSpecializationTypes.InsertNode(T, InsertPos); + DependentTemplateSpecializationTypes.try_emplace(ID, T); return QualType(T, 0); } diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 0f2762d..22bb4cb 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -456,7 +456,9 @@ CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context, const Decl *D1, const Decl *D2, const Decl *PrimaryDecl = nullptr) { // If either declaration has an attribute on it, we treat the declarations - // as not being structurally equivalent. + // as not being structurally equivalent unless both declarations are implicit + // (ones generated by the compiler like __NSConstantString_tag). + // // FIXME: this should be handled on a case-by-case basis via tablegen in // Attr.td. There are multiple cases to consider: one declaration with the // attribute, another without it; different attribute syntax|spellings for @@ -468,7 +470,7 @@ CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context, D1Attr = *D1->getAttrs().begin(); if (D2->hasAttrs()) D2Attr = *D2->getAttrs().begin(); - if (D1Attr || D2Attr) { + if ((D1Attr || D2Attr) && !D1->isImplicit() && !D2->isImplicit()) { const auto *DiagnoseDecl = cast<TypeDecl>(PrimaryDecl ? PrimaryDecl : D2); Context.Diag2(DiagnoseDecl->getLocation(), diag::warn_odr_tag_type_with_attributes) @@ -870,7 +872,27 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, else if (T1->getTypeClass() == Type::FunctionNoProto && T2->getTypeClass() == Type::FunctionProto) TC = Type::FunctionNoProto; - else + else if (Context.LangOpts.C23 && !Context.StrictTypeSpelling && + (T1->getTypeClass() == Type::Enum || + T2->getTypeClass() == Type::Enum)) { + // In C23, if not being strict about token equivalence, we need to handle + // the case where one type is an enumeration and the other type is an + // integral type. + // + // C23 6.7.3.3p16: The enumerated type is compatible with the underlying + // type of the enumeration. + // + // Treat the enumeration as its underlying type and use the builtin type + // class comparison. + if (T1->getTypeClass() == Type::Enum) { + T1 = T1->getAs<EnumType>()->getDecl()->getIntegerType(); + assert(T2->isBuiltinType() && !T1.isNull()); // Sanity check + } else if (T2->getTypeClass() == Type::Enum) { + T2 = T2->getAs<EnumType>()->getDecl()->getIntegerType(); + assert(T1->isBuiltinType() && !T2.isNull()); // Sanity check + } + TC = Type::Builtin; + } else return false; } @@ -2071,6 +2093,48 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, !CheckStructurallyEquivalentAttributes(Context, D1, D2)) return false; + // In C23, if one enumeration has a fixed underlying type, the other shall + // have a compatible fixed underlying type (6.2.7). + if (Context.LangOpts.C23) { + if (D1->isFixed() != D2->isFixed()) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) + << Context.ToCtx.getTypeDeclType(D2) + << (&Context.FromCtx != &Context.ToCtx); + Context.Diag1(D1->getLocation(), + D1->isFixed() + ? diag::note_odr_fixed_underlying_type + : diag::note_odr_missing_fixed_underlying_type) + << D1; + Context.Diag2(D2->getLocation(), + D2->isFixed() + ? diag::note_odr_fixed_underlying_type + : diag::note_odr_missing_fixed_underlying_type) + << D2; + } + return false; + } + if (D1->isFixed()) { + assert(D2->isFixed() && "enums expected to have fixed underlying types"); + if (!IsStructurallyEquivalent(Context, D1->getIntegerType(), + D2->getIntegerType())) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) + << Context.ToCtx.getTypeDeclType(D2) + << (&Context.FromCtx != &Context.ToCtx); + Context.Diag2(D2->getLocation(), + diag::note_odr_incompatible_fixed_underlying_type) + << D2 << D2->getIntegerType() << D1->getIntegerType(); + } + return false; + } + } + } + llvm::SmallVector<const EnumConstantDecl *, 8> D1Enums, D2Enums; auto CopyEnumerators = [](auto &&Range, llvm::SmallVectorImpl<const EnumConstantDecl *> &Cont) { diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 63ac536..d0ddb2e 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -1022,7 +1022,8 @@ bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) { if (classifyPrim(E) != PT_Ptr) return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E); return true; - } else if (Op == BO_Sub) { + } + if (Op == BO_Sub) { if (!this->emitSubOffset(OffsetType, E)) return false; @@ -3703,7 +3704,7 @@ bool Compiler<Emitter>::VisitBlockExpr(const BlockExpr *E) { return true; const Function *Func = nullptr; - if (auto F = Ctx.getOrCreateObjCBlock(E)) + if (const Function *F = Ctx.getOrCreateObjCBlock(E)) Func = F; if (!Func) @@ -4288,7 +4289,8 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) { return false; } return true; - } else if (ElemType->isRecordType()) { + } + if (ElemType->isRecordType()) { const Record *R = getRecord(ElemType); for (size_t I = 0; I != NumElems; ++I) { @@ -4302,7 +4304,8 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) { return false; } return true; - } else if (ElemType->isArrayType()) { + } + if (ElemType->isArrayType()) { for (size_t I = 0; I != NumElems; ++I) { if (!this->emitConstUint32(I, E)) return false; @@ -4774,11 +4777,10 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, if (!this->visit(Init)) return false; return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals(); - } else { + } if (!this->visit(Init)) return false; return this->emitSetLocal(*VarT, Offset, VD); - } } } else { if (std::optional<unsigned> Offset = this->allocateLocal( @@ -4805,7 +4807,7 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType, assert(!DiscardResult); if (Val.isInt()) return this->emitConst(Val.getInt(), ValType, E); - else if (Val.isFloat()) { + if (Val.isFloat()) { APFloat F = Val.getFloat(); return this->emitFloat(F, E); } @@ -4816,9 +4818,8 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType, APValue::LValueBase Base = Val.getLValueBase(); if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>()) return this->visit(BaseExpr); - else if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) { + if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) return this->visitDeclRef(VD, E); - } } else if (Val.isMemberPointer()) { if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl()) return this->emitGetMemberPtr(MemberDecl, E); @@ -4854,7 +4855,8 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val, } } return true; - } else if (Val.isUnion()) { + } + if (Val.isUnion()) { const FieldDecl *UnionField = Val.getUnionField(); const Record *R = this->getRecord(UnionField->getParent()); assert(R); @@ -4864,7 +4866,8 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val, if (!this->visitAPValue(F, T, E)) return false; return this->emitInitField(T, RF->Offset, E); - } else if (Val.isArray()) { + } + if (Val.isArray()) { const auto *ArrType = T->getAsArrayTypeUnsafe(); QualType ElemType = ArrType->getElementType(); for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) { @@ -4981,12 +4984,10 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) { // Calls to replaceable operator new/operator delete. if (FuncDecl->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) { - if (FuncDecl->getDeclName().isAnyOperatorNew()) { + if (FuncDecl->getDeclName().isAnyOperatorNew()) return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_new); - } else { - assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete); - return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete); - } + assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete); + return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete); } // Explicit calls to trivial destructors @@ -5455,7 +5456,9 @@ bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) { return false; this->emitCleanup(); return this->emitRet(*ReturnType, RS); - } else if (RE->getType()->isVoidType()) { + } + + if (RE->getType()->isVoidType()) { if (!this->visit(RE)) return false; } else { @@ -5500,7 +5503,7 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) { if (std::optional<bool> BoolValue = getBoolValue(IS->getCond())) { if (*BoolValue) return visitChildStmt(IS->getThen()); - else if (const Stmt *Else = IS->getElse()) + if (const Stmt *Else = IS->getElse()) return visitChildStmt(Else); return true; } @@ -5992,7 +5995,7 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) { if (!this->emitThis(Ctor)) return false; - auto PVD = Ctor->getParamDecl(0); + const ParmVarDecl *PVD = Ctor->getParamDecl(0); ParamOffset PO = this->Params[PVD]; // Must exist. if (!this->emitGetParam(PT_Ptr, PO.Offset, Ctor)) @@ -6153,7 +6156,7 @@ bool Compiler<Emitter>::compileUnionAssignmentOperator( if (!this->emitThis(MD)) return false; - auto PVD = MD->getParamDecl(0); + const ParmVarDecl *PVD = MD->getParamDecl(0); ParamOffset PO = this->Params[PVD]; // Must exist. if (!this->emitGetParam(PT_Ptr, PO.Offset, MD)) diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 5463aec..224d65c 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -845,7 +845,7 @@ bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { return true; } -bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { +static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) { const SourceLocation &Loc = S.Current->getLocation(OpPC); diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 9012442..2602ed7 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -481,13 +481,11 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { Floating RA = S.allocFloat(A.getSemantics()); RA.copy(ResR); Result.elem<Floating>(0) = RA; // Floating(ResR); - Result.atIndex(0).initialize(); Floating RI = S.allocFloat(A.getSemantics()); RI.copy(ResI); Result.elem<Floating>(1) = RI; // Floating(ResI); - Result.atIndex(1).initialize(); - Result.initialize(); + Result.initializeAllElements(); } else { // Integer element type. const T &LHSR = LHS.elem<T>(0); @@ -505,7 +503,6 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { return false; if (T::sub(A, B, Bits, &Result.elem<T>(0))) return false; - Result.atIndex(0).initialize(); // imag(Result) = (real(LHS) * imag(RHS)) + (imag(LHS) * real(RHS)) if (T::mul(LHSR, RHSI, Bits, &A)) @@ -514,8 +511,8 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { return false; if (T::add(A, B, Bits, &Result.elem<T>(1))) return false; - Result.atIndex(1).initialize(); Result.initialize(); + Result.initializeAllElements(); } return true; @@ -541,14 +538,12 @@ inline bool Divc(InterpState &S, CodePtr OpPC) { Floating RA = S.allocFloat(A.getSemantics()); RA.copy(ResR); Result.elem<Floating>(0) = RA; // Floating(ResR); - Result.atIndex(0).initialize(); Floating RI = S.allocFloat(A.getSemantics()); RI.copy(ResI); Result.elem<Floating>(1) = RI; // Floating(ResI); - Result.atIndex(1).initialize(); - Result.initialize(); + Result.initializeAllElements(); } else { // Integer element type. const T &LHSR = LHS.elem<T>(0); @@ -590,7 +585,6 @@ inline bool Divc(InterpState &S, CodePtr OpPC) { return false; if (T::div(ResultR, Den, Bits, &ResultR)) return false; - Result.atIndex(0).initialize(); // imag(Result) = ((imag(LHS) * real(RHS)) - (real(LHS) * imag(RHS))) / Den if (T::mul(LHSI, RHSR, Bits, &A) || T::mul(LHSR, RHSI, Bits, &B)) @@ -599,8 +593,7 @@ inline bool Divc(InterpState &S, CodePtr OpPC) { return false; if (T::div(ResultI, Den, Bits, &ResultI)) return false; - Result.atIndex(1).initialize(); - Result.initialize(); + Result.initializeAllElements(); } return true; diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 19d4c0c..f908d02 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -240,9 +240,9 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, T CB = PB.deref<T>(); if (CA > CB) return returnResult(1); - else if (CA < CB) + if (CA < CB) return returnResult(-1); - else if (CA.isZero() || CB.isZero()) + if (CA.isZero() || CB.isZero()) return returnResult(0); }); continue; @@ -253,7 +253,7 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, if (CA > CB) return returnResult(1); - else if (CA < CB) + if (CA < CB) return returnResult(-1); if (CA == 0 || CB == 0) return returnResult(0); @@ -1048,7 +1048,7 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC, PtrArg = ICE->getSubExpr(); } - if (auto PtrTy = PtrArg->getType()->getAs<PointerType>()) { + if (const auto *PtrTy = PtrArg->getType()->getAs<PointerType>()) { QualType PointeeType = PtrTy->getPointeeType(); if (!PointeeType->isIncompleteType() && S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) { @@ -1099,10 +1099,8 @@ static bool interp__builtin_complex(InterpState &S, CodePtr OpPC, Pointer &Result = S.Stk.peek<Pointer>(); Result.elem<Floating>(0) = Arg1; - Result.atIndex(0).initialize(); Result.elem<Floating>(1) = Arg2; - Result.atIndex(1).initialize(); - Result.initialize(); + Result.initializeAllElements(); return true; } @@ -1728,9 +1726,9 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC, Dst.elem<T>(I) = T::from(Arg.elem<T>(I).toAPSInt().reverseBits().getZExtValue()); } - Dst.atIndex(I).initialize(); }); } + Dst.initializeAllElements(); return true; } @@ -1967,7 +1965,8 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC, if (A < B) { pushInteger(S, -1, Call->getType()); return true; - } else if (A > B) { + } + if (A > B) { pushInteger(S, 1, Call->getType()); return true; } @@ -1979,7 +1978,8 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC, if (A < B) { pushInteger(S, -1, Call->getType()); return true; - } else if (A > B) { + } + if (A > B) { pushInteger(S, 1, Call->getType()); return true; } @@ -2312,12 +2312,10 @@ static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC, llvm_unreachable("Wrong builtin ID"); } - INT_TYPE_SWITCH_NO_BOOL(ElemT, { - const Pointer &E = Dst.atIndex(I); - E.deref<T>() = static_cast<T>(Result); - E.initialize(); - }); + INT_TYPE_SWITCH_NO_BOOL(ElemT, + { Dst.elem<T>(I) = static_cast<T>(Result); }); } + Dst.initializeAllElements(); return true; } diff --git a/clang/lib/AST/ByteCode/InterpStack.h b/clang/lib/AST/ByteCode/InterpStack.h index 0b76f1d..580494e 100644 --- a/clang/lib/AST/ByteCode/InterpStack.h +++ b/clang/lib/AST/ByteCode/InterpStack.h @@ -14,11 +14,9 @@ #define LLVM_CLANG_AST_INTERP_INTERPSTACK_H #include "FixedPoint.h" -#include "FunctionPointer.h" #include "IntegralAP.h" #include "MemberPointer.h" #include "PrimType.h" -#include <memory> #include <vector> namespace clang { diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 4019b74..4753a4e1 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -16,6 +16,7 @@ #include "MemberPointer.h" #include "PrimType.h" #include "Record.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/RecordLayout.h" @@ -66,14 +67,14 @@ Pointer::~Pointer() { } } -void Pointer::operator=(const Pointer &P) { +Pointer &Pointer::operator=(const Pointer &P) { // If the current storage type is Block, we need to remove // this pointer from the block. if (isBlockPointer()) { if (P.isBlockPointer() && this->block() == P.block()) { Offset = P.Offset; PointeeStorage.BS.Base = P.PointeeStorage.BS.Base; - return; + return *this; } if (Block *Pointee = PointeeStorage.BS.Pointee) { @@ -101,16 +102,17 @@ void Pointer::operator=(const Pointer &P) { } else { assert(false && "Unhandled storage kind"); } + return *this; } -void Pointer::operator=(Pointer &&P) { +Pointer &Pointer::operator=(Pointer &&P) { // If the current storage type is Block, we need to remove // this pointer from the block. if (isBlockPointer()) { if (P.isBlockPointer() && this->block() == P.block()) { Offset = P.Offset; PointeeStorage.BS.Base = P.PointeeStorage.BS.Base; - return; + return *this; } if (Block *Pointee = PointeeStorage.BS.Pointee) { @@ -138,6 +140,7 @@ void Pointer::operator=(Pointer &&P) { } else { assert(false && "Unhandled storage kind"); } + return *this; } APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { @@ -492,6 +495,19 @@ void Pointer::initialize() const { getInlineDesc()->IsInitialized = true; } +void Pointer::initializeAllElements() const { + assert(getFieldDesc()->isPrimitiveArray()); + assert(isArrayRoot()); + + InitMapPtr &IM = getInitMap(); + if (!IM) { + IM = std::make_pair(true, nullptr); + } else { + IM->first = true; + IM->second.reset(); + } +} + void Pointer::activate() const { // Field has its bit in an inline descriptor. assert(PointeeStorage.BS.Base != 0 && @@ -603,7 +619,7 @@ bool Pointer::pointsToStringLiteral() const { return false; const Expr *E = block()->getDescriptor()->asExpr(); - return E && isa<StringLiteral>(E); + return isa_and_nonnull<StringLiteral>(E); } std::optional<std::pair<Pointer, Pointer>> diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index d17eba5..9fe224c 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -120,8 +120,8 @@ public: Pointer(Block *Pointee, unsigned Base, uint64_t Offset); ~Pointer(); - void operator=(const Pointer &P); - void operator=(Pointer &&P); + Pointer &operator=(const Pointer &P); + Pointer &operator=(Pointer &&P); /// Equality operators are just for tests. bool operator==(const Pointer &P) const { @@ -725,6 +725,10 @@ public: /// Initializes a field. void initialize() const; + /// Initialize all elements of a primitive array at once. This can be + /// used in situations where we *know* we have initialized *all* elements + /// of a primtive array. + void initializeAllElements() const; /// Activats a field. void activate() const; /// Deactivates an entire strurcutre. @@ -761,7 +765,7 @@ public: if (Offset < Other.Offset) return ComparisonCategoryResult::Less; - else if (Offset > Other.Offset) + if (Offset > Other.Offset) return ComparisonCategoryResult::Greater; return ComparisonCategoryResult::Equal; diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index 7002724..2421ec4 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -418,7 +418,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, } return allocateDescriptor(D, *T, MDSize, NumElems, IsConst, IsTemporary, IsMutable); - } else { + } // Arrays of composites. In this case, the array is a list of pointers, // followed by the actual elements. const Descriptor *ElemDesc = createDescriptor( @@ -430,7 +430,6 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, return {}; return allocateDescriptor(D, Ty, ElemDesc, MDSize, NumElems, IsConst, IsTemporary, IsMutable); - } } // Array of unknown bounds - cannot be accessed and pointer arithmetic @@ -440,14 +439,13 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, if (OptPrimType T = Ctx.classify(ElemTy)) { return allocateDescriptor(D, *T, MDSize, IsConst, IsTemporary, Descriptor::UnknownSize{}); - } else { + } const Descriptor *Desc = createDescriptor( D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary); if (!Desc) return nullptr; return allocateDescriptor(D, Desc, MDSize, IsTemporary, Descriptor::UnknownSize{}); - } } } diff --git a/clang/lib/AST/ByteCode/Program.h b/clang/lib/AST/ByteCode/Program.h index 5d9c422..207ceef 100644 --- a/clang/lib/AST/ByteCode/Program.h +++ b/clang/lib/AST/ByteCode/Program.h @@ -19,10 +19,7 @@ #include "Record.h" #include "Source.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" -#include <map> #include <vector> namespace clang { diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 2e1a9a3..d85655b 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1629,20 +1629,20 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { return FnType->getReturnType(); } -std::pair<const NamedDecl *, const Attr *> -CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const { +std::pair<const NamedDecl *, const WarnUnusedResultAttr *> +Expr::getUnusedResultAttrImpl(const Decl *Callee, QualType ReturnType) { // If the callee is marked nodiscard, return that attribute - if (const Decl *D = getCalleeDecl()) - if (const auto *A = D->getAttr<WarnUnusedResultAttr>()) + if (Callee != nullptr) + if (const auto *A = Callee->getAttr<WarnUnusedResultAttr>()) return {nullptr, A}; // If the return type is a struct, union, or enum that is marked nodiscard, // then return the return type attribute. - if (const TagDecl *TD = getCallReturnType(Ctx)->getAsTagDecl()) + if (const TagDecl *TD = ReturnType->getAsTagDecl()) if (const auto *A = TD->getAttr<WarnUnusedResultAttr>()) return {TD, A}; - for (const auto *TD = getCallReturnType(Ctx)->getAs<TypedefType>(); TD; + for (const auto *TD = ReturnType->getAs<TypedefType>(); TD; TD = TD->desugar()->getAs<TypedefType>()) if (const auto *A = TD->getDecl()->getAttr<WarnUnusedResultAttr>()) return {TD->getDecl(), A}; @@ -2844,12 +2844,11 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, return true; } - if (const ObjCMethodDecl *MD = ME->getMethodDecl()) - if (MD->hasAttr<WarnUnusedResultAttr>()) { - WarnE = this; - Loc = getExprLoc(); - return true; - } + if (ME->hasUnusedResultAttr(Ctx)) { + WarnE = this; + Loc = getExprLoc(); + return true; + } return false; } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 0d12161..9808298 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14636,7 +14636,9 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) { bool WasArrayIndex; unsigned Mismatch = FindDesignatorMismatch( - getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex); + LHSValue.Base.isNull() ? QualType() + : getType(LHSValue.Base).getNonReferenceType(), + LHSDesignator, RHSDesignator, WasArrayIndex); // At the point where the designators diverge, the comparison has a // specified value if: // - we are comparing array indices @@ -14680,7 +14682,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, // compare pointers within the object in question; otherwise, the result // depends on where the object is located in memory. if (!LHSValue.Base.isNull() && IsRelational) { - QualType BaseTy = getType(LHSValue.Base); + QualType BaseTy = getType(LHSValue.Base).getNonReferenceType(); if (BaseTy->isIncompleteType()) return Error(E); CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy); diff --git a/clang/lib/AST/ExprObjC.cpp b/clang/lib/AST/ExprObjC.cpp index 50d3a447..83419a1 100644 --- a/clang/lib/AST/ExprObjC.cpp +++ b/clang/lib/AST/ExprObjC.cpp @@ -12,6 +12,7 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/ComputeDependence.h" #include "clang/AST/SelectorLocationsKind.h" #include "clang/AST/Type.h" diff --git a/clang/lib/AST/OSLog.cpp b/clang/lib/AST/OSLog.cpp index b777d4d..91f8410 100644 --- a/clang/lib/AST/OSLog.cpp +++ b/clang/lib/AST/OSLog.cpp @@ -1,4 +1,16 @@ -// TODO: header template +//===--- OSLog.cpp - OS log format string analysis ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements analysis functions for OS log format strings and +/// buffer layout computation for __builtin_os_log_format and related builtins. +/// +//===----------------------------------------------------------------------===// #include "clang/AST/OSLog.h" #include "clang/AST/Attr.h" @@ -137,8 +149,8 @@ public: for (auto &Data : ArgsData) { if (!Data.MaskType.empty()) { CharUnits Size = CharUnits::fromQuantity(8); - Layout.Items.emplace_back(OSLogBufferItem::MaskKind, nullptr, - Size, 0, Data.MaskType); + Layout.Items.emplace_back(OSLogBufferItem::MaskKind, nullptr, Size, 0, + Data.MaskType); } if (Data.FieldWidth) { diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 6a74e98..760b2fc 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1953,7 +1953,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, // silently there. For other targets that have ms_struct enabled // (most probably via a pragma or attribute), trigger a diagnostic // that defaults to an error. - if (!Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) + if (!Context.getTargetInfo().getTriple().isOSCygMing()) Diag(D->getLocation(), diag::warn_npot_ms_struct); } if (TypeSize > FieldAlign && |