aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ByteCode/Floating.h3
-rw-r--r--clang/lib/AST/ByteCode/IntegralAP.h2
-rw-r--r--clang/lib/Analysis/ExprMutationAnalyzer.cpp13
-rw-r--r--clang/lib/Basic/SourceManager.cpp18
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp22
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCleanup.cpp8
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCleanup.h71
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp4
-rw-r--r--clang/lib/CIR/CodeGen/EHScopeStack.h8
-rw-r--r--clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp16
-rw-r--r--clang/lib/CodeGen/CGHLSLBuiltins.cpp54
-rw-r--r--clang/lib/Driver/Driver.cpp29
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp9
-rw-r--r--clang/lib/Format/FormatTokenLexer.cpp13
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp23
-rw-r--r--clang/lib/Format/WhitespaceManager.cpp3
-rw-r--r--clang/lib/Frontend/ASTUnit.cpp6
-rw-r--r--clang/lib/Frontend/DependencyFile.cpp11
-rw-r--r--clang/lib/Frontend/InitPreprocessor.cpp6
-rw-r--r--clang/lib/Frontend/TextDiagnostic.cpp76
-rw-r--r--clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h73
-rw-r--r--clang/lib/Headers/module.modulemap5
-rw-r--r--clang/lib/Lex/ModuleMap.cpp1
-rw-r--r--clang/lib/Lex/PPDirectives.cpp2
-rw-r--r--clang/lib/Lex/PPMacroExpansion.cpp14
-rw-r--r--clang/lib/Sema/SemaFunctionEffects.cpp20
-rw-r--r--clang/lib/Sema/SemaHLSL.cpp57
-rw-r--r--clang/lib/Sema/SemaStmt.cpp3
-rw-r--r--clang/lib/Sema/SemaTemplateDeductionGuide.cpp3
-rw-r--r--clang/lib/Sema/SemaType.cpp38
-rw-r--r--clang/lib/Serialization/ASTReader.cpp4
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp3
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp64
-rw-r--r--clang/lib/StaticAnalyzer/Core/CallEvent.cpp18
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Core/RegionStore.cpp48
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))