diff options
Diffstat (limited to 'clang/lib')
36 files changed, 549 insertions, 201 deletions
diff --git a/clang/lib/AST/ByteCode/Floating.h b/clang/lib/AST/ByteCode/Floating.h index 659892e..cc918dc 100644 --- a/clang/lib/AST/ByteCode/Floating.h +++ b/clang/lib/AST/ByteCode/Floating.h @@ -45,7 +45,8 @@ private: if (singleWord()) return APFloat(getSemantics(), APInt(BitWidth, Val)); unsigned NumWords = numWords(); - return APFloat(getSemantics(), APInt(BitWidth, NumWords, Memory)); + return APFloat(getSemantics(), + APInt(BitWidth, llvm::ArrayRef(Memory, NumWords))); } public: diff --git a/clang/lib/AST/ByteCode/IntegralAP.h b/clang/lib/AST/ByteCode/IntegralAP.h index 6683db9..b11e6ee 100644 --- a/clang/lib/AST/ByteCode/IntegralAP.h +++ b/clang/lib/AST/ByteCode/IntegralAP.h @@ -63,7 +63,7 @@ public: if (singleWord()) return APInt(BitWidth, Val, Signed); unsigned NumWords = llvm::APInt::getNumWords(BitWidth); - return llvm::APInt(BitWidth, NumWords, Memory); + return llvm::APInt(BitWidth, llvm::ArrayRef(Memory, NumWords)); } public: diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp index 75b17c54..54c30c0 100644 --- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -746,11 +746,14 @@ ExprMutationAnalyzer::Analyzer::findPointeeMemberMutation(const Expr *Exp) { Stm, Context)); if (MemberCallExpr) return MemberCallExpr; - const auto Matches = - match(stmt(forEachDescendant( - memberExpr(hasObjectExpression(canResolveToExprPointee(Exp))) - .bind(NodeID<Expr>::value))), - Stm, Context); + const auto Matches = match( + stmt(forEachDescendant( + expr(anyOf(memberExpr( + hasObjectExpression(canResolveToExprPointee(Exp))), + binaryOperator(hasOperatorName("->*"), + hasLHS(canResolveToExprPointee(Exp))))) + .bind(NodeID<Expr>::value))), + Stm, Context); return findExprMutation(Matches); } diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 938c648..97aa0f2 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -907,19 +907,23 @@ getExpansionLocSlowCase(SourceLocation Loc) const { SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const { do { - FileIDAndOffset LocInfo = getDecomposedLoc(Loc); - Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc(); - Loc = Loc.getLocWithOffset(LocInfo.second); + const SLocEntry &Entry = getSLocEntry(getFileID(Loc)); + Loc = Entry.getExpansion().getSpellingLoc().getLocWithOffset( + Loc.getOffset() - Entry.getOffset()); } while (!Loc.isFileID()); return Loc; } SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const { do { - if (isMacroArgExpansion(Loc)) - Loc = getImmediateSpellingLoc(Loc); - else - Loc = getImmediateExpansionRange(Loc).getBegin(); + const SLocEntry &Entry = getSLocEntry(getFileID(Loc)); + const ExpansionInfo &ExpInfo = Entry.getExpansion(); + if (ExpInfo.isMacroArgExpansion()) { + Loc = ExpInfo.getSpellingLoc().getLocWithOffset(Loc.getOffset() - + Entry.getOffset()); + } else { + Loc = ExpInfo.getExpansionLocStart(); + } } while (!Loc.isFileID()); return Loc; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index e35100f..0803910 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -211,6 +211,28 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, assert(!cir::MissingFeatures::fastMathFlags()); return emitUnaryMaybeConstrainedFPBuiltin<cir::CosOp>(*this, *e); + case Builtin::BIceil: + case Builtin::BIceilf: + case Builtin::BIceill: + case Builtin::BI__builtin_ceil: + case Builtin::BI__builtin_ceilf: + case Builtin::BI__builtin_ceilf16: + case Builtin::BI__builtin_ceill: + case Builtin::BI__builtin_ceilf128: + assert(!cir::MissingFeatures::fastMathFlags()); + return emitUnaryMaybeConstrainedFPBuiltin<cir::CeilOp>(*this, *e); + + case Builtin::BIexp: + case Builtin::BIexpf: + case Builtin::BIexpl: + case Builtin::BI__builtin_exp: + case Builtin::BI__builtin_expf: + case Builtin::BI__builtin_expf16: + case Builtin::BI__builtin_expl: + case Builtin::BI__builtin_expf128: + assert(!cir::MissingFeatures::fastMathFlags()); + return emitUnaryMaybeConstrainedFPBuiltin<cir::ExpOp>(*this, *e); + case Builtin::BIfabs: case Builtin::BIfabsf: case Builtin::BIfabsl: diff --git a/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp b/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp index 851328a..437db30 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp @@ -147,8 +147,8 @@ void *EHScopeStack::pushCleanup(CleanupKind kind, size_t size) { assert(!cir::MissingFeatures::innermostEHScope()); - EHCleanupScope *scope = new (buffer) - EHCleanupScope(size, branchFixups.size(), innermostNormalCleanup); + EHCleanupScope *scope = new (buffer) EHCleanupScope( + size, branchFixups.size(), innermostNormalCleanup, innermostEHScope); if (isNormalCleanup) innermostNormalCleanup = stable_begin(); @@ -191,7 +191,9 @@ void EHScopeStack::popCleanup() { EHCatchScope *EHScopeStack::pushCatch(unsigned numHandlers) { char *buffer = allocate(EHCatchScope::getSizeForNumHandlers(numHandlers)); assert(!cir::MissingFeatures::innermostEHScope()); - EHCatchScope *scope = new (buffer) EHCatchScope(numHandlers); + EHCatchScope *scope = + new (buffer) EHCatchScope(numHandlers, innermostEHScope); + innermostEHScope = stable_begin(); return scope; } diff --git a/clang/lib/CIR/CodeGen/CIRGenCleanup.h b/clang/lib/CIR/CodeGen/CIRGenCleanup.h index 61a09a5..a035d79 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCleanup.h +++ b/clang/lib/CIR/CodeGen/CIRGenCleanup.h @@ -30,6 +30,8 @@ struct CatchTypeInfo { /// A protected scope for zero-cost EH handling. class EHScope { + EHScopeStack::stable_iterator enclosingEHScope; + class CommonBitFields { friend class EHScope; unsigned kind : 3; @@ -79,7 +81,10 @@ protected: public: enum Kind { Cleanup, Catch, Terminate, Filter }; - EHScope(Kind kind) { commonBits.kind = kind; } + EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope) + : enclosingEHScope(enclosingEHScope) { + commonBits.kind = kind; + } Kind getKind() const { return static_cast<Kind>(commonBits.kind); } @@ -90,6 +95,10 @@ public: assert(!cir::MissingFeatures::ehstackBranches()); return false; } + + EHScopeStack::stable_iterator getEnclosingEHScope() const { + return enclosingEHScope; + } }; /// A scope which attempts to handle some, possibly all, types of @@ -111,6 +120,8 @@ public: /// The catch handler for this type. mlir::Region *region; + + bool isCatchAll() const { return type.rtti == nullptr; } }; private: @@ -118,12 +129,18 @@ private: Handler *getHandlers() { return reinterpret_cast<Handler *>(this + 1); } + const Handler *getHandlers() const { + return reinterpret_cast<const Handler *>(this + 1); + } + public: static size_t getSizeForNumHandlers(unsigned n) { return sizeof(EHCatchScope) + n * sizeof(Handler); } - EHCatchScope(unsigned numHandlers) : EHScope(Catch) { + EHCatchScope(unsigned numHandlers, + EHScopeStack::stable_iterator enclosingEHScope) + : EHScope(Catch, enclosingEHScope) { catchBits.numHandlers = numHandlers; assert(catchBits.numHandlers == numHandlers && "NumHandlers overflow?"); } @@ -136,6 +153,11 @@ public: getHandlers()[i].region = region; } + const Handler &getHandler(unsigned i) const { + assert(i < getNumHandlers()); + return getHandlers()[i]; + } + // Clear all handler blocks. // FIXME: it's better to always call clearHandlerBlocks in DTOR and have a // 'takeHandler' or some such function which removes ownership from the @@ -144,6 +166,10 @@ public: // The blocks are owned by TryOp, nothing to delete. } + using iterator = const Handler *; + iterator begin() const { return getHandlers(); } + iterator end() const { return getHandlers() + getNumHandlers(); } + static bool classof(const EHScope *scope) { return scope->getKind() == Catch; } @@ -176,9 +202,10 @@ public: } EHCleanupScope(unsigned cleanupSize, unsigned fixupDepth, - EHScopeStack::stable_iterator enclosingNormal) - : EHScope(EHScope::Cleanup), enclosingNormal(enclosingNormal), - fixupDepth(fixupDepth) { + EHScopeStack::stable_iterator enclosingNormal, + EHScopeStack::stable_iterator enclosingEH) + : EHScope(EHScope::Cleanup, enclosingEH), + enclosingNormal(enclosingNormal), fixupDepth(fixupDepth) { // TODO(cir): When exception handling is upstreamed, isNormalCleanup and // isEHCleanup will be arguments to the constructor. cleanupBits.isNormalCleanup = true; @@ -235,13 +262,45 @@ public: EHScope *get() const { return reinterpret_cast<EHScope *>(ptr); } + EHScope *operator->() const { return get(); } EHScope &operator*() const { return *get(); } + + iterator &operator++() { + size_t size; + switch (get()->getKind()) { + case EHScope::Catch: + size = EHCatchScope::getSizeForNumHandlers( + static_cast<const EHCatchScope *>(get())->getNumHandlers()); + break; + + case EHScope::Filter: + llvm_unreachable("EHScopeStack::iterator Filter"); + break; + + case EHScope::Cleanup: + llvm_unreachable("EHScopeStack::iterator Cleanup"); + break; + + case EHScope::Terminate: + llvm_unreachable("EHScopeStack::iterator Terminate"); + break; + } + ptr += llvm::alignTo(size, ScopeStackAlignment); + return *this; + } + + bool operator==(iterator other) const { return ptr == other.ptr; } + bool operator!=(iterator other) const { return ptr != other.ptr; } }; inline EHScopeStack::iterator EHScopeStack::begin() const { return iterator(startOfData); } +inline EHScopeStack::iterator EHScopeStack::end() const { + return iterator(endOfBuffer); +} + inline EHScopeStack::iterator EHScopeStack::find(stable_iterator savePoint) const { assert(savePoint.isValid() && "finding invalid savepoint"); @@ -254,7 +313,7 @@ inline void EHScopeStack::popCatch() { assert(!empty() && "popping exception stack when not empty"); EHCatchScope &scope = llvm::cast<EHCatchScope>(*begin()); - assert(!cir::MissingFeatures::innermostEHScope()); + innermostEHScope = scope.getEnclosingEHScope(); deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers())); } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index 3d3030c..201fb73 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -343,8 +343,8 @@ public: cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitNoInitExpr"); } void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) { - cgf.cgm.errorNYI(dae->getSourceRange(), - "AggExprEmitter: VisitCXXDefaultArgExpr"); + CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae); + Visit(dae->getExpr()); } void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *e) { cgf.cgm.errorNYI(e->getSourceRange(), diff --git a/clang/lib/CIR/CodeGen/EHScopeStack.h b/clang/lib/CIR/CodeGen/EHScopeStack.h index 4198c23..9005b01 100644 --- a/clang/lib/CIR/CodeGen/EHScopeStack.h +++ b/clang/lib/CIR/CodeGen/EHScopeStack.h @@ -155,6 +155,9 @@ private: /// The innermost normal cleanup on the stack. stable_iterator innermostNormalCleanup = stable_end(); + /// The innermost EH scope on the stack. + stable_iterator innermostEHScope = stable_end(); + /// The CGF this Stack belong to CIRGenFunction *cgf = nullptr; @@ -226,6 +229,8 @@ public: } stable_iterator getInnermostActiveNormalCleanup() const; + stable_iterator getInnermostEHScope() const { return innermostEHScope; } + /// An unstable reference to a scope-stack depth. Invalidated by /// pushes but not pops. class iterator; @@ -233,6 +238,9 @@ public: /// Returns an iterator pointing to the innermost EH scope. iterator begin() const; + /// Returns an iterator pointing to the outermost EH scope. + iterator end() const; + /// Create a stable reference to the top of the EH stack. The /// returned reference is valid until that scope is popped off the /// stack. diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 5a6193f..ba967a4 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -194,6 +194,14 @@ mlir::LogicalResult CIRToLLVMCosOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMExpOpLowering::matchAndRewrite( + cir::ExpOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Type resTy = typeConverter->convertType(op.getType()); + rewriter.replaceOpWithNewOp<mlir::LLVM::ExpOp>(op, resTy, adaptor.getSrc()); + return mlir::success(); +} + static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter, mlir::Value llvmSrc, mlir::Type llvmDstIntTy, bool isUnsigned, uint64_t cirSrcWidth, @@ -1336,6 +1344,14 @@ mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMCeilOpLowering::matchAndRewrite( + cir::CeilOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Type resTy = typeConverter->convertType(op.getType()); + rewriter.replaceOpWithNewOp<mlir::LLVM::FCeilOp>(op, resTy, adaptor.getSrc()); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite( cir::AllocaOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index fbf4a57..b6928ce 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -160,6 +160,57 @@ static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) { return LastInst; } +static Value *handleElementwiseF16ToF32(CodeGenFunction &CGF, + const CallExpr *E) { + Value *Op0 = CGF.EmitScalarExpr(E->getArg(0)); + QualType Op0Ty = E->getArg(0)->getType(); + llvm::Type *ResType = CGF.FloatTy; + uint64_t NumElements = 0; + if (Op0->getType()->isVectorTy()) { + NumElements = + E->getArg(0)->getType()->castAs<clang::VectorType>()->getNumElements(); + ResType = + llvm::VectorType::get(ResType, ElementCount::getFixed(NumElements)); + } + if (!Op0Ty->hasUnsignedIntegerRepresentation()) + llvm_unreachable( + "f16tof32 operand must have an unsigned int representation"); + + if (CGF.CGM.getTriple().isDXIL()) + return CGF.Builder.CreateIntrinsic(ResType, Intrinsic::dx_legacyf16tof32, + ArrayRef<Value *>{Op0}, nullptr, + "hlsl.f16tof32"); + + if (CGF.CGM.getTriple().isSPIRV()) { + // We use the SPIRV UnpackHalf2x16 operation to avoid the need for the + // Int16 and Float16 capabilities + auto UnpackType = + llvm::VectorType::get(CGF.FloatTy, ElementCount::getFixed(2)); + if (NumElements == 0) { + // a scalar input - simply extract the first element of the unpacked + // vector + Value *Unpack = CGF.Builder.CreateIntrinsic( + UnpackType, Intrinsic::spv_unpackhalf2x16, ArrayRef<Value *>{Op0}); + return CGF.Builder.CreateExtractElement(Unpack, (uint64_t)0); + } else { + // a vector input - build a congruent output vector by iterating through + // the input vector calling unpackhalf2x16 for each element + Value *Result = PoisonValue::get(ResType); + for (uint64_t i = 0; i < NumElements; i++) { + Value *InVal = CGF.Builder.CreateExtractElement(Op0, i); + Value *Unpack = CGF.Builder.CreateIntrinsic( + UnpackType, Intrinsic::spv_unpackhalf2x16, + ArrayRef<Value *>{InVal}); + Value *Res = CGF.Builder.CreateExtractElement(Unpack, (uint64_t)0); + Result = CGF.Builder.CreateInsertElement(Result, Res, i); + } + return Result; + } + } + + llvm_unreachable("Intrinsic F16ToF32 not supported by target architecture"); +} + static Value *emitBufferStride(CodeGenFunction *CGF, const Expr *HandleExpr, LValue &Stride) { // Figure out the stride of the buffer elements from the handle type. @@ -579,6 +630,9 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getDegreesIntrinsic(), ArrayRef<Value *>{X}, nullptr, "hlsl.degrees"); } + case Builtin::BI__builtin_hlsl_elementwise_f16tof32: { + return handleElementwiseF16ToF32(*this, E); + } case Builtin::BI__builtin_hlsl_elementwise_frac: { Value *Op0 = EmitScalarExpr(E->getArg(0)); if (!E->getArg(0)->getType()->hasFloatingRepresentation()) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 51618d1..a0b82ce 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3857,6 +3857,9 @@ class OffloadingActionBuilder final { /// Flag set to true if all valid builders allow file bundling/unbundling. bool CanUseBundler; + /// Flag set to false if an argument turns off bundling. + bool ShouldUseBundler; + public: OffloadingActionBuilder(Compilation &C, DerivedArgList &Args, const Driver::InputList &Inputs) @@ -3891,6 +3894,9 @@ public: } CanUseBundler = ValidBuilders && ValidBuilders == ValidBuildersSupportingBundling; + + ShouldUseBundler = Args.hasFlag(options::OPT_gpu_bundle_output, + options::OPT_no_gpu_bundle_output, true); } ~OffloadingActionBuilder() { @@ -4042,11 +4048,11 @@ public: SB->appendTopLevelActions(OffloadAL); } - // If we can use the bundler, replace the host action by the bundling one in - // the resulting list. Otherwise, just append the device actions. For - // device only compilation, HostAction is a null pointer, therefore only do - // this when HostAction is not a null pointer. - if (CanUseBundler && HostAction && + // If we can and should use the bundler, replace the host action by the + // bundling one in the resulting list. Otherwise, just append the device + // actions. For device only compilation, HostAction is a null pointer, + // therefore only do this when HostAction is not a null pointer. + if (CanUseBundler && ShouldUseBundler && HostAction && HostAction->getType() != types::TY_Nothing && !OffloadAL.empty()) { // Add the host action to the list in order to create the bundling action. OffloadAL.push_back(HostAction); @@ -6463,9 +6469,16 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, (JA.getOffloadingDeviceKind() == Action::OFK_OpenMP && TC && TC->getTriple().isAMDGPU())); }; - if (!AtTopLevel && JA.getType() == types::TY_LLVM_BC && - (C.getArgs().hasArg(options::OPT_emit_llvm) || - IsAMDRDCInCompilePhase(JA, C.getArgs()))) + + // The linker wrapper may not support the input and output files to be the + // same one, and without it -save-temps can fail. + bool IsLinkerWrapper = + JA.getType() == types::TY_Object && isa<LinkerWrapperJobAction>(JA); + bool IsEmitBitcode = JA.getType() == types::TY_LLVM_BC && + (C.getArgs().hasArg(options::OPT_emit_llvm) || + IsAMDRDCInCompilePhase(JA, C.getArgs())); + + if (!AtTopLevel && (IsLinkerWrapper || IsEmitBitcode)) Suffixed += ".tmp"; Suffixed += '.'; Suffixed += Suffix; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index d3ab6f1..30d3e52 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7879,10 +7879,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, !TC.getTriple().isAndroid() && TC.useIntegratedAs())) CmdArgs.push_back("-faddrsig"); - if ((Triple.isOSBinFormatELF() || Triple.isOSBinFormatMachO()) && + const bool HasDefaultDwarf2CFIASM = + (Triple.isOSBinFormatELF() || Triple.isOSBinFormatMachO()) && (EH || UnwindTables || AsyncUnwindTables || - DebugInfoKind != llvm::codegenoptions::NoDebugInfo)) - CmdArgs.push_back("-D__GCC_HAVE_DWARF2_CFI_ASM=1"); + DebugInfoKind != llvm::codegenoptions::NoDebugInfo); + if (Args.hasFlag(options::OPT_fdwarf2_cfi_asm, + options::OPT_fno_dwarf2_cfi_asm, HasDefaultDwarf2CFIASM)) + CmdArgs.push_back("-fdwarf2-cfi-asm"); if (Arg *A = Args.getLastArg(options::OPT_fsymbol_partition_EQ)) { std::string Str = A->getAsString(Args); diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index ab32938..a9ea5ec 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -318,14 +318,21 @@ void FormatTokenLexer::tryMergePreviousTokens() { {tok::equal, tok::greater}, {tok::star, tok::greater}, {tok::pipeequal, tok::greater}, - {tok::pipe, tok::arrow}, - {tok::hash, tok::minus, tok::hash}, - {tok::hash, tok::equal, tok::hash}}, + {tok::pipe, tok::arrow}}, TT_BinaryOperator) || Tokens.back()->is(tok::arrow)) { Tokens.back()->ForcedPrecedence = prec::Comma; return; } + if (Tokens.size() >= 3 && + Tokens[Tokens.size() - 3]->is(Keywords.kw_verilogHash) && + Tokens[Tokens.size() - 2]->isOneOf(tok::minus, tok::equal) && + Tokens[Tokens.size() - 1]->is(Keywords.kw_verilogHash) && + tryMergeTokens(3, TT_BinaryOperator)) { + Tokens.back()->setFinalizedType(TT_BinaryOperator); + Tokens.back()->ForcedPrecedence = prec::Comma; + return; + } } else if (Style.isTableGen()) { // TableGen's Multi line string starts with [{ if (tryMergeTokens({tok::l_square, tok::l_brace}, diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 8e227da..cb41756c 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -358,11 +358,11 @@ private: Contexts.back().IsExpression = false; } else if (OpeningParen.Previous && (OpeningParen.Previous->isOneOf( - tok::kw_static_assert, tok::kw_noexcept, tok::kw_explicit, - tok::kw_while, tok::l_paren, tok::comma, TT_CastRParen, + tok::kw_noexcept, tok::kw_explicit, tok::kw_while, + tok::l_paren, tok::comma, TT_CastRParen, TT_BinaryOperator) || OpeningParen.Previous->isIf())) { - // static_assert, if and while usually contain expressions. + // if and while usually contain expressions. Contexts.back().IsExpression = true; } else if (Style.isJavaScript() && OpeningParen.Previous && (OpeningParen.Previous->is(Keywords.kw_function) || @@ -454,6 +454,11 @@ private: if (StartsObjCSelector) OpeningParen.setType(TT_ObjCSelector); + const bool IsStaticAssert = + PrevNonComment && PrevNonComment->is(tok::kw_static_assert); + if (IsStaticAssert) + Contexts.back().InStaticAssertFirstArgument = true; + // MightBeFunctionType and ProbablyFunctionType are used for // function pointer and reference types as well as Objective-C // block types: @@ -583,8 +588,12 @@ private: } // When we discover a 'new', we set CanBeExpression to 'false' in order to // parse the type correctly. Reset that after a comma. - if (CurrentToken->is(tok::comma)) - Contexts.back().CanBeExpression = true; + if (CurrentToken->is(tok::comma)) { + if (IsStaticAssert) + Contexts.back().InStaticAssertFirstArgument = false; + else + Contexts.back().CanBeExpression = true; + } if (Style.isTableGen()) { if (CurrentToken->is(tok::comma)) { @@ -2144,6 +2153,7 @@ private: bool CaretFound = false; bool InCpp11AttributeSpecifier = false; bool InCSharpAttributeSpecifier = false; + bool InStaticAssertFirstArgument = false; bool VerilogAssignmentFound = false; // Whether the braces may mean concatenation instead of structure or array // literal. @@ -2440,7 +2450,8 @@ private: } else if (Current.isPointerOrReference()) { Current.setType(determineStarAmpUsage( Current, - Contexts.back().CanBeExpression && Contexts.back().IsExpression, + (Contexts.back().CanBeExpression && Contexts.back().IsExpression) || + Contexts.back().InStaticAssertFirstArgument, Contexts.back().ContextType == Context::TemplateArgument)); } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret) || (Style.isVerilog() && Current.is(tok::pipe))) { diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index f24b8ab..406c77c 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -591,7 +591,8 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, CurrentChangeWidthRight = CurrentChange.TokenLength; const FormatToken *MatchingParenToEncounter = nullptr; for (unsigned J = I + 1; - J != E && (Changes[J].NewlinesBefore == 0 || MatchingParenToEncounter); + J != E && (Changes[J].NewlinesBefore == 0 || + MatchingParenToEncounter || Changes[J].IsAligned); ++J) { const auto &Change = Changes[J]; const auto *Tok = Change.Tok; diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 6cc7094..1169acb 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -518,14 +518,14 @@ class ASTInfoCollector : public ASTReaderListener { LangOptions &LangOpts; CodeGenOptions &CodeGenOpts; TargetOptions &TargetOpts; - unsigned &Counter; + uint32_t &Counter; public: ASTInfoCollector(HeaderSearchOptions &HSOpts, std::string &SpecificModuleCachePath, PreprocessorOptions &PPOpts, LangOptions &LangOpts, CodeGenOptions &CodeGenOpts, TargetOptions &TargetOpts, - unsigned &Counter) + uint32_t &Counter) : HSOpts(HSOpts), SpecificModuleCachePath(SpecificModuleCachePath), PPOpts(PPOpts), LangOpts(LangOpts), CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), Counter(Counter) {} @@ -577,7 +577,7 @@ public: } void ReadCounter(const serialization::ModuleFile &M, - unsigned NewCounter) override { + uint32_t NewCounter) override { Counter = NewCounter; } }; diff --git a/clang/lib/Frontend/DependencyFile.cpp b/clang/lib/Frontend/DependencyFile.cpp index 15fa7de..93e012b 100644 --- a/clang/lib/Frontend/DependencyFile.cpp +++ b/clang/lib/Frontend/DependencyFile.cpp @@ -75,6 +75,17 @@ struct DepCollectorPPCallbacks : public PPCallbacks { /*IsMissing*/ false); } + bool EmbedFileNotFound(StringRef FileName) override { + DepCollector.maybeAddDependency( + llvm::sys::path::remove_leading_dotslash(FileName), + /*FromModule=*/false, + /*IsSystem=*/false, + /*IsModuleFile=*/false, + /*IsMissing=*/true); + // Return true to silence the file not found diagnostic. + return true; + } + void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 8602be1..b88d9f8 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -1516,6 +1516,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (LangOpts.PointerAuthIntrinsics) Builder.defineMacro("__PTRAUTH__"); + if (CGOpts.Dwarf2CFIAsm) + Builder.defineMacro("__GCC_HAVE_DWARF2_CFI_ASM"); + // Get other target #defines. TI.getTargetDefines(LangOpts, Builder); } @@ -1542,6 +1545,9 @@ void clang::InitializePreprocessor(Preprocessor &PP, llvm::raw_string_ostream Predefines(PredefineBuffer); MacroBuilder Builder(Predefines); + // Ensure that the initial value of __COUNTER__ is hooked up. + PP.setCounterValue(InitOpts.InitialCounterValue); + // Emit line markers for various builtin sections of the file. The 3 here // marks <built-in> as being a system header, which suppresses warnings when // the same macro is defined multiple times. diff --git a/clang/lib/Frontend/TextDiagnostic.cpp b/clang/lib/Frontend/TextDiagnostic.cpp index aea3e72..1003218 100644 --- a/clang/lib/Frontend/TextDiagnostic.cpp +++ b/clang/lib/Frontend/TextDiagnostic.cpp @@ -349,14 +349,13 @@ private: /// When the source code line we want to print is too long for /// the terminal, select the "interesting" region. -static void selectInterestingSourceRegion(std::string &SourceLine, - std::string &CaretLine, - std::string &FixItInsertionLine, - Columns NonGutterColumns, - const SourceColumnMap &Map) { - Columns CaretColumns = Columns(CaretLine.size()); - Columns FixItColumns = - Columns(llvm::sys::locale::columnWidth(FixItInsertionLine)); +static void selectInterestingSourceRegion( + std::string &SourceLine, std::string &CaretLine, + std::string &FixItInsertionLine, Columns NonGutterColumns, + const SourceColumnMap &Map, + SmallVectorImpl<clang::TextDiagnostic::StyleRange> &Styles) { + Columns CaretColumns = CaretLine.size(); + Columns FixItColumns = llvm::sys::locale::columnWidth(FixItInsertionLine); Columns MaxColumns = std::max({Map.columns().V, CaretColumns.V, FixItColumns.V}); // if the number of columns is less than the desired number we're done @@ -369,13 +368,11 @@ static void selectInterestingSourceRegion(std::string &SourceLine, // Find the slice that we need to display the full caret line // correctly. Columns CaretStart = 0, CaretEnd = CaretLine.size(); - for (; CaretStart != CaretEnd; CaretStart = CaretStart.next()) - if (!isWhitespace(CaretLine[CaretStart.V])) - break; + while (CaretStart != CaretEnd && isWhitespace(CaretLine[CaretStart.V])) + CaretStart = CaretStart.next(); - for (; CaretEnd != CaretStart; CaretEnd = CaretEnd.prev()) - if (!isWhitespace(CaretLine[CaretEnd.V - 1])) - break; + while (CaretEnd != CaretStart && isWhitespace(CaretLine[CaretEnd.V])) + CaretEnd = CaretEnd.prev(); // caret has already been inserted into CaretLine so the above whitespace // check is guaranteed to include the caret @@ -516,13 +513,45 @@ static void selectInterestingSourceRegion(std::string &SourceLine, assert(FrontColumnsRemoved + ColumnsKept + BackColumnsRemoved > NonGutterColumns); + // Since we've modified the SourceLine, we also need to adjust the line's + // highlighting information. In particular, if we've removed + // from the front of the line, we need to move the style ranges to the + // left and remove unneeded ranges. + // Note in particular that variables like CaretEnd are defined in the + // CaretLine, which only contains ASCII, while the style ranges are defined in + // the source line, where we have to care for the byte-index != column-index + // case. + Bytes BytesRemoved = + FrontColumnsRemoved > FrontEllipse.size() + ? (Map.columnToByte(FrontColumnsRemoved) - Bytes(FrontEllipse.size())) + : 0; + Bytes CodeEnd = + CaretEnd < Map.columns() ? Map.columnToByte(CaretEnd.V) : CaretEnd.V; + for (TextDiagnostic::StyleRange &R : Styles) { + // Remove style ranges before and after the new truncated snippet. + if (R.Start >= static_cast<unsigned>(CodeEnd.V) || + R.End < static_cast<unsigned>(BytesRemoved.V)) { + R.Start = R.End = std::numeric_limits<int>::max(); + continue; + } + // Move them left. (Note that this can wrap R.Start, but that doesn't + // matter). + R.Start -= BytesRemoved.V; + R.End -= BytesRemoved.V; + + // Don't leak into the ellipse at the end. + if (R.Start < static_cast<unsigned>(CodeEnd.V) && + R.End > static_cast<unsigned>(CodeEnd.V)) + R.End = CodeEnd.V + 1; // R.End is inclusive. + } + // The line needs some truncation, and we'd prefer to keep the front // if possible, so remove the back if (BackColumnsRemoved > Columns(BackEllipse.size())) SourceLine.replace(SourceEnd.V, std::string::npos, BackEllipse); // If that's enough then we're done - if (FrontColumnsRemoved + ColumnsKept <= Columns(NonGutterColumns)) + if (FrontColumnsRemoved + ColumnsKept <= NonGutterColumns) return; // Otherwise remove the front as well @@ -1391,6 +1420,11 @@ void TextDiagnostic::emitSnippetAndCaret( OS.indent(MaxLineNoDisplayWidth + 2) << "| "; }; + Columns MessageLength = DiagOpts.MessageLength; + // If we don't have enough columns available, just abort now. + if (MessageLength != 0 && MessageLength <= Columns(MaxLineNoDisplayWidth + 4)) + return; + // Prepare source highlighting information for the lines we're about to // emit, starting from the first line. std::unique_ptr<SmallVector<StyleRange>[]> SourceStyles = @@ -1450,10 +1484,14 @@ void TextDiagnostic::emitSnippetAndCaret( // If the source line is too long for our terminal, select only the // "interesting" source region within that line. - Columns MessageLength = DiagOpts.MessageLength; - if (MessageLength.V != 0) + if (MessageLength != 0) { + Columns NonGutterColumns = MessageLength; + if (MaxLineNoDisplayWidth != 0) + NonGutterColumns -= Columns(MaxLineNoDisplayWidth + 4); selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine, - MessageLength, SourceColMap); + NonGutterColumns, SourceColMap, + SourceStyles[LineNo - Lines.first]); + } // If we are in -fdiagnostics-print-source-range-info mode, we are trying // to produce easily machine parsable output. Add a space before the @@ -1508,7 +1546,7 @@ void TextDiagnostic::emitSnippet(StringRef SourceLine, // Print the source line one character at a time. bool PrintReversed = false; std::optional<llvm::raw_ostream::Colors> CurrentColor; - size_t I = 0; + size_t I = 0; // Bytes. while (I < SourceLine.size()) { auto [Str, WasPrintable] = printableTextForNextCharacter(SourceLine, &I, DiagOpts.TabStop); diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h index a918af3..208776e 100644 --- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h @@ -1053,6 +1053,27 @@ _HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2) float4 exp2(float4); //===----------------------------------------------------------------------===// +// f16tof32 builtins +//===----------------------------------------------------------------------===// + +/// \fn float f16tof32(uint x) +/// \brief Returns the half value stored in the low 16 bits of the uint arg +/// converted to a float. +/// \param x The uint containing two half values. +/// +/// The float value of the half value found in the low 16 bits of the \a xi +/// parameter. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_f16tof32) +float f16tof32(uint); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_f16tof32) +float2 f16tof32(uint2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_f16tof32) +float3 f16tof32(uint3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_f16tof32) +float4 f16tof32(uint4); + +//===----------------------------------------------------------------------===// // firstbithigh builtins //===----------------------------------------------------------------------===// @@ -2090,9 +2111,17 @@ T select(bool, T, T); /// \param FalseVals The vector values are chosen from when conditions are /// false. -template <typename T, int Sz> +template <typename T> _HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) -vector<T, Sz> select(vector<bool, Sz>, vector<T, Sz>, vector<T, Sz>); +vector<T, 2> select(vector<bool, 2>, vector<T, 2>, vector<T, 2>); + +template <typename T> +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +vector<T, 3> select(vector<bool, 3>, vector<T, 3>, vector<T, 3>); + +template <typename T> +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +vector<T, 4> select(vector<bool, 4>, vector<T, 4>, vector<T, 4>); /// \fn vector<T,Sz> select(vector<bool,Sz> Conds, T TrueVal, /// vector<T,Sz> FalseVals) @@ -2102,9 +2131,17 @@ vector<T, Sz> select(vector<bool, Sz>, vector<T, Sz>, vector<T, Sz>); /// \param FalseVals The vector values are chosen from when conditions are /// false. -template <typename T, int Sz> +template <typename T> +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +vector<T, 2> select(vector<bool, 2>, T, vector<T, 2>); + +template <typename T> +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +vector<T, 3> select(vector<bool, 3>, T, vector<T, 3>); + +template <typename T> _HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) -vector<T, Sz> select(vector<bool, Sz>, T, vector<T, Sz>); +vector<T, 4> select(vector<bool, 4>, T, vector<T, 4>); /// \fn vector<T,Sz> select(vector<bool,Sz> Conds, vector<T,Sz> TrueVals, /// T FalseVal) @@ -2113,9 +2150,17 @@ vector<T, Sz> select(vector<bool, Sz>, T, vector<T, Sz>); /// \param TrueVals The vector values are chosen from when conditions are true. /// \param FalseVal The scalar value to splat from when conditions are false. -template <typename T, int Sz> +template <typename T> _HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) -vector<T, Sz> select(vector<bool, Sz>, vector<T, Sz>, T); +vector<T, 2> select(vector<bool, 2>, vector<T, 2>, T); + +template <typename T> +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +vector<T, 3> select(vector<bool, 3>, vector<T, 3>, T); + +template <typename T> +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +vector<T, 4> select(vector<bool, 4>, vector<T, 4>, T); /// \fn vector<T,Sz> select(vector<bool,Sz> Conds, vector<T,Sz> TrueVals, /// T FalseVal) @@ -2124,10 +2169,20 @@ vector<T, Sz> select(vector<bool, Sz>, vector<T, Sz>, T); /// \param TrueVal The scalar value to splat from when conditions are true. /// \param FalseVal The scalar value to splat from when conditions are false. -template <typename T, int Sz> +template <typename T> +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +__detail::enable_if_t<__detail::is_arithmetic<T>::Value, vector<T, 2>> select( + vector<bool, 2>, T, T); + +template <typename T> +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) +__detail::enable_if_t<__detail::is_arithmetic<T>::Value, vector<T, 3>> select( + vector<bool, 3>, T, T); + +template <typename T> _HLSL_BUILTIN_ALIAS(__builtin_hlsl_select) -__detail::enable_if_t<__detail::is_arithmetic<T>::Value, vector<T, Sz>> select( - vector<bool, Sz>, T, T); +__detail::enable_if_t<__detail::is_arithmetic<T>::Value, vector<T, 4>> select( + vector<bool, 4>, T, T); //===----------------------------------------------------------------------===// // sin builtins diff --git a/clang/lib/Headers/module.modulemap b/clang/lib/Headers/module.modulemap index 2e4d533..c13dd3f 100644 --- a/clang/lib/Headers/module.modulemap +++ b/clang/lib/Headers/module.modulemap @@ -253,6 +253,11 @@ module _Builtin_stdbool [system] { export * } +module _Builtin_stdckdint [system] { + header "stdckdint.h" + export * +} + module _Builtin_stdcountof [system] { header "stdcountof.h" export * diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 637a08f..b8202ea 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -258,6 +258,7 @@ static bool isBuiltinHeaderName(StringRef FileName) { .Case("stdarg.h", true) .Case("stdatomic.h", true) .Case("stdbool.h", true) + .Case("stdckdint.h", true) .Case("stdcountof.h", true) .Case("stddef.h", true) .Case("stdint.h", true) diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 6a5e5d4..891c8ab 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -4018,7 +4018,7 @@ void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc, Token &EmbedTok, this->LookupEmbedFile(Filename, isAngled, true, LookupFromFile); if (!MaybeFileRef) { // could not find file - if (Callbacks && Callbacks->EmbedFileNotFound(OriginalFilename)) { + if (Callbacks && Callbacks->EmbedFileNotFound(Filename)) { return; } Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index dd80ae5..5efa4b5 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1735,7 +1735,19 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Diag(getLastFPEvalPragmaLocation(), diag::note_pragma_entered_here); } } else if (II == Ident__COUNTER__) { - // __COUNTER__ expands to a simple numeric value. + Diag(Tok.getLocation(), + getLangOpts().C2y ? diag::warn_counter : diag::ext_counter); + // __COUNTER__ expands to a simple numeric value that must be less than + // 2147483647. + constexpr uint32_t MaxPosValue = std::numeric_limits<int32_t>::max(); + if (CounterValue > MaxPosValue) { + Diag(Tok.getLocation(), diag::err_counter_overflow); + // Retain the maximal value so we don't issue conversion-related + // diagnostics by overflowing into a long long. While this does produce + // a duplicate value, there's no way to ignore this error so there's no + // translation anyway. + CounterValue = MaxPosValue; + } OS << CounterValue++; Tok.setKind(tok::numeric_constant); } else if (II == Ident__has_feature) { diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp index 8590ee8..4b63eb7 100644 --- a/clang/lib/Sema/SemaFunctionEffects.cpp +++ b/clang/lib/Sema/SemaFunctionEffects.cpp @@ -1208,8 +1208,16 @@ private: return true; } - // No Decl, just an Expr. Just check based on its type. - checkIndirectCall(Call, CalleeExpr->getType()); + // No Decl, just an Expr. Just check based on its type. Bound member + // functions are a special expression type and need to be specially + // unpacked. + QualType CalleeExprQT = CalleeExpr->getType(); + if (CalleeExpr->isBoundMemberFunction(Outer.S.getASTContext())) { + QualType QT = Expr::findBoundMemberType(CalleeExpr); + if (!QT.isNull()) + CalleeExprQT = QT; + } + checkIndirectCall(Call, CalleeExprQT); return true; } @@ -1271,7 +1279,15 @@ private: const CXXConstructorDecl *Ctor = Construct->getConstructor(); CallableInfo CI(*Ctor); followCall(CI, Construct->getLocation()); + return true; + } + bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *BTE) override { + const CXXDestructorDecl *Dtor = BTE->getTemporary()->getDestructor(); + if (Dtor != nullptr) { + CallableInfo CI(*Dtor); + followCall(CI, BTE->getBeginLoc()); + } return true; } diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 94a490a..b9707f0 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -2802,6 +2802,23 @@ static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc, return false; } +static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall, + unsigned ArgOrdinal, unsigned Width) { + QualType ArgTy = TheCall->getArg(0)->getType(); + if (auto *VTy = ArgTy->getAs<VectorType>()) + ArgTy = VTy->getElementType(); + // ensure arg type has expected bit width + uint64_t ElementBitCount = + S->getASTContext().getTypeSizeInChars(ArgTy).getQuantity() * 8; + if (ElementBitCount != Width) { + S->Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_integer_incorrect_bit_count) + << Width << ElementBitCount; + return true; + } + return false; +} + static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType) { auto *VecTyA = TheCall->getArg(0)->getType()->getAs<VectorType>(); @@ -2961,24 +2978,16 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { CheckUnsignedIntVecRepresentation)) return true; - auto *VTy = TheCall->getArg(0)->getType()->getAs<VectorType>(); // ensure arg integers are 32-bits - uint64_t ElementBitCount = getASTContext() - .getTypeSizeInChars(VTy->getElementType()) - .getQuantity() * - 8; - if (ElementBitCount != 32) { - SemaRef.Diag(TheCall->getBeginLoc(), - diag::err_integer_incorrect_bit_count) - << 32 << ElementBitCount; + if (CheckExpectedBitWidth(&SemaRef, TheCall, 0, 32)) return true; - } // ensure both args are vectors of total bit size of a multiple of 64 + auto *VTy = TheCall->getArg(0)->getType()->getAs<VectorType>(); int NumElementsArg = VTy->getNumElements(); if (NumElementsArg != 2 && NumElementsArg != 4) { SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vector_incorrect_bit_count) - << 1 /*a multiple of*/ << 64 << NumElementsArg * ElementBitCount; + << 1 /*a multiple of*/ << 64 << NumElementsArg * 32; return true; } @@ -3295,7 +3304,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } // Note these are llvm builtins that we want to catch invalid intrinsic - // generation. Normal handling of these builitns will occur elsewhere. + // generation. Normal handling of these builtins will occur elsewhere. case Builtin::BI__builtin_elementwise_bitreverse: { // does not include a check for number of arguments // because that is done previously @@ -3405,6 +3414,30 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { } break; } + case Builtin::BI__builtin_hlsl_elementwise_f16tof32: { + if (SemaRef.checkArgCount(TheCall, 1)) + return true; + if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall, + CheckUnsignedIntRepresentation)) + return true; + // ensure arg integers are 32 bits + if (CheckExpectedBitWidth(&SemaRef, TheCall, 0, 32)) + return true; + // check it wasn't a bool type + QualType ArgTy = TheCall->getArg(0)->getType(); + if (auto *VTy = ArgTy->getAs<VectorType>()) + ArgTy = VTy->getElementType(); + if (ArgTy->isBooleanType()) { + SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_builtin_invalid_arg_type) + << 1 << /* scalar or vector of */ 5 << /* unsigned int */ 3 + << /* no fp */ 0 << TheCall->getArg(0)->getType(); + return true; + } + + SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().FloatTy); + break; + } } return false; } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index f398963..5b3ef1a 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3281,6 +3281,9 @@ static Scope *FindLabeledBreakContinueScope(Sema &S, Scope *CurScope, SourceLocation LabelLoc, bool IsContinue) { assert(Target && "not a named break/continue?"); + + Target->markUsed(S.Context); + Scope *Found = nullptr; for (Scope *Scope = CurScope; Scope; Scope = Scope->getParent()) { if (Scope->isFunctionScope()) diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index ad50600..bfcd397 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -659,7 +659,8 @@ private: SemaRef, MaterializedTypedefs, NestedPattern, TransformingOuterPatterns ? &Args : nullptr) .transform(NewDI); - + if (!NewDI) + return nullptr; // Resolving a wording defect, we also inherit default arguments from the // constructor. ExprResult NewDefArg; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 280b3c9..c483930 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2358,6 +2358,11 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, return QualType(); } + if (VecSize->isNegative()) { + Diag(SizeExpr->getExprLoc(), diag::err_attribute_vec_negative_size); + return QualType(); + } + if (CurType->isDependentType()) return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, VectorKind::Generic); @@ -2394,7 +2399,7 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, VectorKind::Generic); } -QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, +QualType Sema::BuildExtVectorType(QualType T, Expr *SizeExpr, SourceLocation AttrLoc) { // Unlike gcc's vector_size attribute, we do not allow vectors to be defined // in conjunction with complex types (pointers, arrays, functions, etc.). @@ -2417,35 +2422,40 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, BIT && CheckBitIntElementType(*this, AttrLoc, BIT)) return QualType(); - if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) { - std::optional<llvm::APSInt> vecSize = - ArraySize->getIntegerConstantExpr(Context); - if (!vecSize) { + if (!SizeExpr->isTypeDependent() && !SizeExpr->isValueDependent()) { + std::optional<llvm::APSInt> VecSize = + SizeExpr->getIntegerConstantExpr(Context); + if (!VecSize) { Diag(AttrLoc, diag::err_attribute_argument_type) - << "ext_vector_type" << AANT_ArgumentIntegerConstant - << ArraySize->getSourceRange(); + << "ext_vector_type" << AANT_ArgumentIntegerConstant + << SizeExpr->getSourceRange(); + return QualType(); + } + + if (VecSize->isNegative()) { + Diag(SizeExpr->getExprLoc(), diag::err_attribute_vec_negative_size); return QualType(); } - if (!vecSize->isIntN(32)) { + if (!VecSize->isIntN(32)) { Diag(AttrLoc, diag::err_attribute_size_too_large) - << ArraySize->getSourceRange() << "vector"; + << SizeExpr->getSourceRange() << "vector"; return QualType(); } // Unlike gcc's vector_size attribute, the size is specified as the // number of elements, not the number of bytes. - unsigned vectorSize = static_cast<unsigned>(vecSize->getZExtValue()); + unsigned VectorSize = static_cast<unsigned>(VecSize->getZExtValue()); - if (vectorSize == 0) { + if (VectorSize == 0) { Diag(AttrLoc, diag::err_attribute_zero_size) - << ArraySize->getSourceRange() << "vector"; + << SizeExpr->getSourceRange() << "vector"; return QualType(); } - return Context.getExtVectorType(T, vectorSize); + return Context.getExtVectorType(T, VectorSize); } - return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc); + return Context.getDependentSizedExtVectorType(T, SizeExpr, AttrLoc); } QualType Sema::BuildMatrixType(QualType ElementTy, Expr *NumRows, Expr *NumCols, diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index e3106f8d..d552821 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -225,7 +225,7 @@ bool ChainedASTReaderListener::ReadPreprocessorOptions( } void ChainedASTReaderListener::ReadCounter(const serialization::ModuleFile &M, - unsigned Value) { + uint32_t Value) { First->ReadCounter(M, Value); Second->ReadCounter(M, Value); } @@ -973,7 +973,7 @@ bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, PP.getPreprocessorOpts()); } -void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) { +void PCHValidator::ReadCounter(const ModuleFile &M, uint32_t Value) { PP.setCounterValue(Value); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 3ac338e..b1fd151 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4374,8 +4374,7 @@ private: // parent of parent. We DON'T remove the enum constant from its parent. So // we don't need to care about merging problems here. if (auto *ECD = dyn_cast<EnumConstantDecl>(D); - ECD && DC.isFileContext() && ECD->getOwningModule() && - ECD->getTopLevelOwningNamedModule()->isNamedModule()) { + ECD && DC.isFileContext() && ECD->getTopLevelOwningNamedModule()) { if (llvm::all_of( DC.noload_lookup( cast<EnumDecl>(ECD->getDeclContext())->getDeclName()), diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 70baab5..ec7ef23 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -6,41 +6,45 @@ // //===----------------------------------------------------------------------===// // -// This file defines a variety of memory management related checkers, such as +// This file defines checkers that report memory management errors such as // leak, double free, and use-after-free. // -// The following checkers are defined here: +// The logic for modeling memory allocations is implemented in the checker +// family which is called 'MallocChecker' for historical reasons. (This name is +// inaccurate, something like 'DynamicMemory' would be more precise.) // -// * MallocChecker -// Despite its name, it models all sorts of memory allocations and -// de- or reallocation, including but not limited to malloc, free, -// relloc, new, delete. It also reports on a variety of memory misuse -// errors. -// Many other checkers interact very closely with this checker, in fact, -// most are merely options to this one. Other checkers may register -// MallocChecker, but do not enable MallocChecker's reports (more details -// to follow around its field, ChecksEnabled). -// It also has a boolean "Optimistic" checker option, which if set to true -// will cause the checker to model user defined memory management related -// functions annotated via the attribute ownership_takes, ownership_holds -// and ownership_returns. +// The reports produced by this backend are exposed through several frontends: +// * MallocChecker: reports all misuse of dynamic memory allocated by +// malloc, related functions (like calloc, realloc etc.) and the functions +// annotated by ownership_returns. (Here the name "MallocChecker" is +// reasonably accurate; don't confuse this checker frontend with the whole +// misnamed family.) +// * NewDeleteChecker: reports most misuse (anything but memory leaks) of +// memory managed by the C++ operators new and new[]. +// * NewDeleteLeaksChecker: reports leaks of dynamic memory allocated by +// the C++ operators new and new[]. +// * MismatchedDeallocatorChecker: reports situations where the allocation +// and deallocation is mismatched, e.g. memory allocated via malloc is +// passed to operator delete. +// * InnerPointerChecker: reports use of pointers to the internal buffer of +// a std::string instance after operations that invalidate them. +// * TaintedAllocChecker: reports situations where the size argument of a +// memory allocation function or array new operator is tainted (i.e. comes +// from an untrusted source and can be controlled by an attacker). // -// * NewDeleteChecker -// Enables the modeling of new, new[], delete, delete[] in MallocChecker, -// and checks for related double-free and use-after-free errors. +// In addition to these frontends this file also defines the registration +// functions for "unix.DynamicMemoryModeling". This registers the callbacks of +// the checker family MallocChecker without enabling any of the frontends and +// and handle two checker options which are attached to this "modeling +// checker" because they affect multiple checker frontends. // -// * NewDeleteLeaksChecker -// Checks for leaks related to new, new[], delete, delete[]. -// Depends on NewDeleteChecker. -// -// * MismatchedDeallocatorChecker -// Enables checking whether memory is deallocated with the corresponding -// allocation function in MallocChecker, such as malloc() allocated -// regions are only freed by free(), new by delete, new[] by delete[]. -// -// InnerPointerChecker interacts very closely with MallocChecker, but unlike -// the above checkers, it has it's own file, hence the many InnerPointerChecker -// related headers and non-static functions. +// Note that what the users see as the checker "cplusplus.InnerPointer" is a +// combination of the frontend InnerPointerChecker (within this family) which +// emits the bug reports and a separate checker class (also named +// InnerPointerChecker) which is defined in InnerPointerChecker.cpp and does a +// significant part of the modeling. This cooperation is enabled by several +// non-static helper functions that are defined within this translation unit +// and used in InnerPointerChecker.cpp. // //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index 62460cc..d04c827 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -230,13 +230,11 @@ static void findPtrToConstParams(llvm::SmallSet<unsigned, 4> &PreserveArgs, } ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount, - ProgramStateRef Orig) const { - ProgramStateRef Result = (Orig ? Orig : getState()); - + ProgramStateRef State) const { // Don't invalidate anything if the callee is marked pure/const. - if (const Decl *callee = getDecl()) - if (callee->hasAttr<PureAttr>() || callee->hasAttr<ConstAttr>()) - return Result; + if (const Decl *Callee = getDecl()) + if (Callee->hasAttr<PureAttr>() || Callee->hasAttr<ConstAttr>()) + return State; SmallVector<SVal, 8> ValuesToInvalidate; RegionAndSymbolInvalidationTraits ETraits; @@ -278,10 +276,10 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount, // Invalidate designated regions using the batch invalidation API. // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate // global variables. - return Result->invalidateRegions(ValuesToInvalidate, getCFGElementRef(), - BlockCount, getLocationContext(), - /*CausedByPointerEscape*/ true, - /*Symbols=*/nullptr, this, &ETraits); + return State->invalidateRegions(ValuesToInvalidate, getCFGElementRef(), + BlockCount, getLocationContext(), + /*CausedByPointerEscape*/ true, + /*Symbols=*/nullptr, this, &ETraits); } ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit, diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 75d7e26..00e3ef8 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -1013,7 +1013,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // FIXME: Once we figure out how we want allocators to work, // we should be using the usual pre-/(default-)eval-/post-call checkers // here. - State = Call->invalidateRegions(blockCount); + State = Call->invalidateRegions(blockCount, State); if (!State) return; diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 2838533..4f4824a 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -714,11 +714,6 @@ public: // Part of public interface to class. return getBinding(getRegionBindings(S), L, T); } - std::optional<SVal> getUniqueDefaultBinding(RegionBindingsConstRef B, - const TypedValueRegion *R) const; - std::optional<SVal> - getUniqueDefaultBinding(nonloc::LazyCompoundVal LCV) const; - std::optional<SVal> getDefaultBinding(Store S, const MemRegion *R) override { RegionBindingsRef B = getRegionBindings(S); // Default bindings are always applied over a base region so look up the @@ -2465,11 +2460,6 @@ SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B, // behavior doesn't depend on the struct layout. // This way even an empty struct can carry taint, no matter if creduce drops // the last field member or not. - - // Try to avoid creating a LCV if it would anyways just refer to a single - // default binding. - if (std::optional<SVal> Val = getUniqueDefaultBinding(B, R)) - return *Val; return createLazyBinding(B, R); } @@ -2757,50 +2747,12 @@ RegionStoreManager::bindVector(LimitedRegionBindingsConstRef B, return NewB; } -std::optional<SVal> -RegionStoreManager::getUniqueDefaultBinding(RegionBindingsConstRef B, - const TypedValueRegion *R) const { - if (R != R->getBaseRegion()) - return std::nullopt; - - const auto *Cluster = B.lookup(R); - if (!Cluster || !llvm::hasSingleElement(*Cluster)) - return std::nullopt; - - const auto [Key, Value] = *Cluster->begin(); - return Key.isDirect() ? std::optional<SVal>{} : Value; -} - -std::optional<SVal> -RegionStoreManager::getUniqueDefaultBinding(nonloc::LazyCompoundVal LCV) const { - auto B = getRegionBindings(LCV.getStore()); - return getUniqueDefaultBinding(B, LCV.getRegion()); -} - std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallStruct( LimitedRegionBindingsConstRef B, const TypedValueRegion *R, const RecordDecl *RD, nonloc::LazyCompoundVal LCV) { if (B.hasExhaustedBindingLimit()) return B.withValuesEscaped(LCV); - // If we try to copy a Conjured value representing the value of the whole - // struct, don't try to element-wise copy each field. - // That would unnecessarily bind Derived symbols slicing off the subregion for - // the field from the whole Conjured symbol. - // - // struct Window { int width; int height; }; - // Window getWindow(); <-- opaque fn. - // Window w = getWindow(); <-- conjures a new Window. - // Window w2 = w; <-- trivial copy "w", calling "tryBindSmallStruct" - // - // We should not end up with a new Store for "w2" like this: - // Direct [ 0..31]: Derived{Conj{}, w.width} - // Direct [32..63]: Derived{Conj{}, w.height} - // Instead, we should just bind that Conjured value instead. - if (std::optional<SVal> Val = getUniqueDefaultBinding(LCV)) { - return B.addBinding(BindingKey::Make(R, BindingKey::Default), Val.value()); - } - FieldVector Fields; if (const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD)) |
