diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaARM.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaConcept.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 42 | ||||
-rw-r--r-- | clang/lib/Sema/SemaHLSL.cpp | 39 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 48 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 4 |
7 files changed, 99 insertions, 68 deletions
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index e09c352..1c7c832d 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -603,8 +603,8 @@ static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, bool SatisfiesSME = Builtin::evaluateRequiredTargetFeatures( StreamingBuiltinGuard, CallerFeatures); - if ((SatisfiesSVE && SatisfiesSME) || - (SatisfiesSVE && FnType == SemaARM::ArmStreamingCompatible)) + if (SatisfiesSVE && SatisfiesSME) + // Function type is irrelevant for streaming-agnostic builtins. return false; else if (SatisfiesSVE) BuiltinType = SemaARM::ArmNonStreaming; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 3cc61b1..063db05 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -8811,8 +8811,10 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, case ArgType::Match: case ArgType::MatchPromotion: case ArgType::NoMatchPromotionTypeConfusion: - case ArgType::NoMatchSignedness: llvm_unreachable("expected non-matching"); + case ArgType::NoMatchSignedness: + Diag = diag::warn_format_conversion_argument_type_mismatch_signedness; + break; case ArgType::NoMatchPedantic: Diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; break; diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 999e302c..f4df63c 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -280,6 +280,11 @@ public: if (T->getDepth() >= TemplateArgs.getNumLevels()) return true; + // There might not be a corresponding template argument before substituting + // into the parameter mapping, e.g. a sizeof... expression. + if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) + return true; + TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex()); if (T->isParameterPack() && SemaRef.ArgPackSubstIndex) { @@ -300,6 +305,12 @@ public: if (!NTTP) return TraverseDecl(D); + if (NTTP->getDepth() >= TemplateArgs.getNumLevels()) + return true; + + if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), NTTP->getIndex())) + return true; + TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition()); if (NTTP->isParameterPack() && SemaRef.ArgPackSubstIndex) { assert(Arg.getKind() == TemplateArgument::Pack && @@ -326,17 +337,25 @@ public: return inherited::TraverseDecl(D); } + bool TraverseCallExpr(CallExpr *CE) { + inherited::TraverseStmt(CE->getCallee()); + + for (Expr *Arg : CE->arguments()) + inherited::TraverseStmt(Arg); + + return true; + } + bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) { // We don't care about TypeLocs. So traverse Types instead. - return TraverseType(TL.getType(), TraverseQualifier); + return TraverseType(TL.getType().getCanonicalType(), TraverseQualifier); } bool TraverseTagType(const TagType *T, bool TraverseQualifier) { // T's parent can be dependent while T doesn't have any template arguments. // We should have already traversed its qualifier. // FIXME: Add an assert to catch cases where we failed to profile the - // concept. assert(!T->isDependentType() && "We missed a case in profiling - // concepts!"); + // concept. return true; } @@ -701,7 +720,6 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID); Iter != S.UnsubstitutedConstraintSatisfactionCache.end()) { - auto &Cached = Iter->second.Satisfaction; Satisfaction.ContainsErrors = Cached.ContainsErrors; Satisfaction.IsSatisfied = Cached.IsSatisfied; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index d27f767..215431c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -9546,14 +9546,32 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( CXXMethodDecl *Decl = SMOR.getMethod(); FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>(); - int DiagKind = -1; - - if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) - DiagKind = !Decl ? 0 : 1; - else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) - DiagKind = 2; + enum { + NotSet = -1, + NoDecl, + DeletedDecl, + MultipleDecl, + InaccessibleDecl, + NonTrivialDecl + } DiagKind = NotSet; + + if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) { + if (CSM == CXXSpecialMemberKind::DefaultConstructor && Field && + Field->getParent()->isUnion()) { + // [class.default.ctor]p2: + // A defaulted default constructor for class X is defined as deleted if + // - X is a union that has a variant member with a non-trivial default + // constructor and no variant member of X has a default member + // initializer + const auto *RD = cast<CXXRecordDecl>(Field->getParent()); + if (RD->hasInClassInitializer()) + return false; + } + DiagKind = !Decl ? NoDecl : DeletedDecl; + } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) + DiagKind = MultipleDecl; else if (!isAccessible(Subobj, Decl)) - DiagKind = 3; + DiagKind = InaccessibleDecl; else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() && !Decl->isTrivial()) { // A member of a union must have a trivial corresponding special member. @@ -9569,13 +9587,13 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( // initializer const auto *RD = cast<CXXRecordDecl>(Field->getParent()); if (!RD->hasInClassInitializer()) - DiagKind = 4; + DiagKind = NonTrivialDecl; } else { - DiagKind = 4; + DiagKind = NonTrivialDecl; } } - if (DiagKind == -1) + if (DiagKind == NotSet) return false; if (Diagnose) { @@ -9593,9 +9611,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( << /*IsObjCPtr*/ false; } - if (DiagKind == 1) + if (DiagKind == DeletedDecl) S.NoteDeletedFunction(Decl); - // FIXME: Explain inaccessibility if DiagKind == 3. + // FIXME: Explain inaccessibility if DiagKind == InaccessibleDecl. } return true; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 2b375b9..09e5d69 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -598,18 +598,17 @@ void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) { validatePackoffset(SemaRef, BufDecl); - // create buffer layout struct createHostLayoutStructForBuffer(SemaRef, BufDecl); - HLSLVkBindingAttr *VkBinding = Dcl->getAttr<HLSLVkBindingAttr>(); - HLSLResourceBindingAttr *RBA = Dcl->getAttr<HLSLResourceBindingAttr>(); - if (!VkBinding && (!RBA || !RBA->hasRegisterSlot())) { + // Handle implicit binding if needed. + ResourceBindingAttrs ResourceAttrs(Dcl); + if (!ResourceAttrs.isExplicit()) { SemaRef.Diag(Dcl->getLocation(), diag::warn_hlsl_implicit_binding); // Use HLSLResourceBindingAttr to transfer implicit binding order_ID // to codegen. If it does not exist, create an implicit attribute. uint32_t OrderID = getNextImplicitBindingOrderID(); - if (RBA) - RBA->setImplicitBindingOrderID(OrderID); + if (ResourceAttrs.hasBinding()) + ResourceAttrs.setImplicitOrderID(OrderID); else addImplicitBindingAttrToDecl(SemaRef, BufDecl, BufDecl->isCBuffer() ? RegisterType::CBuffer @@ -1289,8 +1288,8 @@ bool SemaHLSL::handleRootSignatureElements( VerifyRegister(Loc, Descriptor->Reg.Number); VerifySpace(Loc, Descriptor->Space); - if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag( - Version, llvm::to_underlying(Descriptor->Flags))) + if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version, + Descriptor->Flags)) ReportFlagError(Loc); } else if (const auto *Constants = std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) { @@ -1590,10 +1589,6 @@ void SemaHLSL::handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL) { } void SemaHLSL::handleVkBindingAttr(Decl *D, const ParsedAttr &AL) { - // The vk::binding attribute only applies to SPIR-V. - if (!getASTContext().getTargetInfo().getTriple().isSPIRV()) - return; - uint32_t Binding = 0; if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Binding)) return; @@ -3780,17 +3775,15 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) { // If the resource array does not have an explicit binding attribute, // create an implicit one. It will be used to transfer implicit binding // order_ID to codegen. - if (!VD->hasAttr<HLSLVkBindingAttr>()) { - HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>(); - if (!RBA || !RBA->hasRegisterSlot()) { - uint32_t OrderID = getNextImplicitBindingOrderID(); - if (RBA) - RBA->setImplicitBindingOrderID(OrderID); - else - addImplicitBindingAttrToDecl( - SemaRef, VD, getRegisterType(getResourceArrayHandleType(VD)), - OrderID); - } + ResourceBindingAttrs Binding(VD); + if (!Binding.isExplicit()) { + uint32_t OrderID = getNextImplicitBindingOrderID(); + if (Binding.hasBinding()) + Binding.setImplicitOrderID(OrderID); + else + addImplicitBindingAttrToDecl( + SemaRef, VD, getRegisterType(getResourceArrayHandleType(VD)), + OrderID); } } } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 922fcac..543db46 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3920,6 +3920,7 @@ bool InitializationSequence::isAmbiguous() const { case FK_AddressOfUnaddressableFunction: case FK_ParenthesizedListInitFailed: case FK_DesignatedInitForNonAggregate: + case FK_HLSLInitListFlatteningFailed: return false; case FK_ReferenceInitOverloadFailed: @@ -4882,8 +4883,10 @@ static void TryListInitialization(Sema &S, bool TreatUnavailableAsInvalid) { QualType DestType = Entity.getType(); - if (S.getLangOpts().HLSL && !S.HLSL().transformInitList(Entity, InitList)) + if (S.getLangOpts().HLSL && !S.HLSL().transformInitList(Entity, InitList)) { + Sequence.SetFailed(InitializationSequence::FK_HLSLInitListFlatteningFailed); return; + } // C++ doesn't allow scalar initialization with more than one argument. // But C99 complex numbers are scalars and it makes sense there. @@ -6817,33 +6820,18 @@ void InitializationSequence::InitializeFrom(Sema &S, assert(Args.size() >= 1 && "Zero-argument case handled above"); // For HLSL ext vector types we allow list initialization behavior for C++ - // constructor syntax. This is accomplished by converting initialization - // arguments an InitListExpr late. + // functional cast expressions which look like constructor syntax. This is + // accomplished by converting initialization arguments to InitListExpr. if (S.getLangOpts().HLSL && Args.size() > 1 && DestType->isExtVectorType() && (SourceType.isNull() || !Context.hasSameUnqualifiedType(SourceType, DestType))) { - - llvm::SmallVector<Expr *> InitArgs; - for (auto *Arg : Args) { - if (Arg->getType()->isExtVectorType()) { - const auto *VTy = Arg->getType()->castAs<ExtVectorType>(); - unsigned Elm = VTy->getNumElements(); - for (unsigned Idx = 0; Idx < Elm; ++Idx) { - InitArgs.emplace_back(new (Context) ArraySubscriptExpr( - Arg, - IntegerLiteral::Create( - Context, llvm::APInt(Context.getIntWidth(Context.IntTy), Idx), - Context.IntTy, SourceLocation()), - VTy->getElementType(), Arg->getValueKind(), Arg->getObjectKind(), - SourceLocation())); - } - } else - InitArgs.emplace_back(Arg); - } - InitListExpr *ILE = new (Context) InitListExpr( - S.getASTContext(), SourceLocation(), InitArgs, SourceLocation()); + InitListExpr *ILE = new (Context) + InitListExpr(S.getASTContext(), Args.front()->getBeginLoc(), Args, + Args.back()->getEndLoc()); + ILE->setType(DestType); Args[0] = ILE; - AddListInitializationStep(DestType); + TryListInitialization(S, Entity, Kind, ILE, *this, + TreatUnavailableAsInvalid); return; } @@ -9301,6 +9289,14 @@ bool InitializationSequence::Diagnose(Sema &S, break; } + case InitializationSequence::FK_HLSLInitListFlatteningFailed: { + // Unlike C/C++ list initialization, there is no fallback if it fails. This + // allows us to diagnose the failure when it happens in the + // TryListInitialization call instead of delaying the diagnosis, which is + // beneficial because the flattening is also expensive. + break; + } + case FK_ExplicitConstructor: { S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor) << Args[0]->getSourceRange(); @@ -9499,6 +9495,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { case FK_DesignatedInitForNonAggregate: OS << "designated initializer for non-aggregate type"; break; + + case FK_HLSLInitListFlatteningFailed: + OS << "HLSL initialization list flattening failed"; + break; } OS << '\n'; return; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 5657dfe..8d32ef6 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1087,14 +1087,14 @@ static bool shouldAddReversedEqEq(Sema &S, SourceLocation OpLoc, } bool OverloadCandidateSet::OperatorRewriteInfo::allowsReversed( - OverloadedOperatorKind Op) { + OverloadedOperatorKind Op) const { if (!AllowRewrittenCandidates) return false; return Op == OO_EqualEqual || Op == OO_Spaceship; } bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed( - Sema &S, ArrayRef<Expr *> OriginalArgs, FunctionDecl *FD) { + Sema &S, ArrayRef<Expr *> OriginalArgs, FunctionDecl *FD) const { auto Op = FD->getOverloadedOperator(); if (!allowsReversed(Op)) return false; |