aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ByteCode/ByteCodeEmitter.cpp19
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp49
-rw-r--r--clang/lib/AST/ByteCode/Compiler.h1
-rw-r--r--clang/lib/AST/ByteCode/Descriptor.cpp46
-rw-r--r--clang/lib/AST/ByteCode/DynamicAllocator.cpp19
-rw-r--r--clang/lib/AST/ByteCode/Interp.h25
-rw-r--r--clang/lib/AST/ByteCode/InterpState.cpp22
-rw-r--r--clang/lib/AST/ByteCode/Opcodes.td4
-rw-r--r--clang/lib/AST/Decl.cpp9
-rw-r--r--clang/lib/AST/Expr.cpp14
-rw-r--r--clang/lib/AST/ExprConstant.cpp94
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp3
-rw-r--r--clang/lib/Analysis/RetainSummaryManager.cpp3
-rw-r--r--clang/lib/Basic/Cuda.cpp6
-rw-r--r--clang/lib/Basic/OffloadArch.cpp4
-rw-r--r--clang/lib/Basic/SourceManager.cpp14
-rw-r--r--clang/lib/Basic/Targets/ARM.cpp21
-rw-r--r--clang/lib/Basic/Targets/NVPTX.cpp12
-rw-r--r--clang/lib/Basic/Targets/WebAssembly.cpp23
-rw-r--r--clang/lib/Basic/Targets/WebAssembly.h2
-rw-r--r--clang/lib/CIR/CodeGen/Address.h11
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCall.h2
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenClass.cpp19
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenDecl.cpp64
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExpr.cpp181
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp88
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp30
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.cpp14
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.h29
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp19
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp4
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp136
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp121
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenStmt.cpp17
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenerator.cpp21
-rw-r--r--clang/lib/CIR/Dialect/IR/CIRDialect.cpp12
-rw-r--r--clang/lib/CIR/Dialect/IR/CIRTypes.cpp17
-rw-r--r--clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp22
-rw-r--r--clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp156
-rw-r--r--clang/lib/CIR/FrontendAction/CIRGenAction.cpp10
-rw-r--r--clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp13
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp6
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp18
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.h1
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp1
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenAction.cpp4
-rw-r--r--clang/lib/CodeGen/CoverageMappingGen.cpp7
-rw-r--r--clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp2
-rw-r--r--clang/lib/CrossTU/CrossTranslationUnit.cpp9
-rw-r--r--clang/lib/Driver/Driver.cpp19
-rw-r--r--clang/lib/Driver/ToolChains/BareMetal.cpp3
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp38
-rw-r--r--clang/lib/Driver/ToolChains/CommonArgs.cpp35
-rw-r--r--clang/lib/Driver/ToolChains/Cuda.cpp23
-rw-r--r--clang/lib/Format/IntegerLiteralSeparatorFixer.cpp13
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp48
-rw-r--r--clang/lib/Frontend/ASTMerge.cpp4
-rw-r--r--clang/lib/Frontend/ASTUnit.cpp95
-rw-r--r--clang/lib/Frontend/ChainedIncludesSource.cpp30
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp69
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp4
-rw-r--r--clang/lib/Frontend/FrontendAction.cpp129
-rw-r--r--clang/lib/Frontend/PrecompiledPreamble.cpp25
-rw-r--r--clang/lib/Frontend/SerializedDiagnosticPrinter.cpp5
-rw-r--r--clang/lib/Headers/__clang_cuda_runtime_wrapper.h5
-rw-r--r--clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h2
-rw-r--r--clang/lib/Headers/hlsl/hlsl_intrinsics.h2
-rw-r--r--clang/lib/Interpreter/CodeCompletion.cpp14
-rw-r--r--clang/lib/Interpreter/Interpreter.cpp6
-rw-r--r--clang/lib/Sema/AnalysisBasedWarnings.cpp4
-rw-r--r--clang/lib/Sema/MultiplexExternalSemaSource.cpp25
-rw-r--r--clang/lib/Sema/Sema.cpp16
-rw-r--r--clang/lib/Sema/SemaAMDGPU.cpp16
-rw-r--r--clang/lib/Sema/SemaChecking.cpp4
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp8
-rw-r--r--clang/lib/Sema/SemaDecl.cpp17
-rw-r--r--clang/lib/Sema/SemaSYCL.cpp31
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp3
-rw-r--r--clang/lib/Serialization/ASTReader.cpp3
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp3
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp38
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp146
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp30
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp98
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp79
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp3
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Core/MemRegion.cpp10
-rw-r--r--clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp14
-rw-r--r--clang/lib/Tooling/CompilationDatabase.cpp5
-rw-r--r--clang/lib/Tooling/Core/Replacement.cpp7
-rw-r--r--clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp4
-rw-r--r--clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp26
-rw-r--r--clang/lib/Tooling/Refactoring.cpp5
-rw-r--r--clang/lib/Tooling/Tooling.cpp38
96 files changed, 1728 insertions, 904 deletions
diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
index 3288585..d474605 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -137,21 +137,21 @@ int32_t ByteCodeEmitter::getOffset(LabelTy Label) {
template <typename T>
static void emit(Program &P, std::vector<std::byte> &Code, const T &Val,
bool &Success) {
+ size_t ValPos = Code.size();
size_t Size;
if constexpr (std::is_pointer_v<T>)
- Size = sizeof(uint32_t);
+ Size = align(sizeof(uint32_t));
else
- Size = sizeof(T);
+ Size = align(sizeof(T));
- if (Code.size() + Size > std::numeric_limits<unsigned>::max()) {
+ if (ValPos + Size > std::numeric_limits<unsigned>::max()) {
Success = false;
return;
}
// Access must be aligned!
- size_t ValPos = align(Code.size());
- Size = align(Size);
+ assert(aligned(ValPos));
assert(aligned(ValPos + Size));
Code.resize(ValPos + Size);
@@ -168,17 +168,16 @@ static void emit(Program &P, std::vector<std::byte> &Code, const T &Val,
template <typename T>
static void emitSerialized(std::vector<std::byte> &Code, const T &Val,
bool &Success) {
- size_t Size = Val.bytesToSerialize();
+ size_t ValPos = Code.size();
+ size_t Size = align(Val.bytesToSerialize());
- if (Code.size() + Size > std::numeric_limits<unsigned>::max()) {
+ if (ValPos + Size > std::numeric_limits<unsigned>::max()) {
Success = false;
return;
}
// Access must be aligned!
- assert(aligned(Code.size()));
- size_t ValPos = Code.size();
- Size = align(Size);
+ assert(aligned(ValPos));
assert(aligned(ValPos + Size));
Code.resize(ValPos + Size);
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index d0ddb2e..6e451ac 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -106,25 +106,14 @@ bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const {
return true;
}
-/// Scope managing label targets.
-template <class Emitter> class LabelScope {
-public:
- virtual ~LabelScope() {}
-
-protected:
- LabelScope(Compiler<Emitter> *Ctx) : Ctx(Ctx) {}
- /// Compiler instance.
- Compiler<Emitter> *Ctx;
-};
-
/// Sets the context for break/continue statements.
-template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
+template <class Emitter> class LoopScope final {
public:
using LabelTy = typename Compiler<Emitter>::LabelTy;
using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
LoopScope(Compiler<Emitter> *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel)
- : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
+ : Ctx(Ctx), OldBreakLabel(Ctx->BreakLabel),
OldContinueLabel(Ctx->ContinueLabel),
OldBreakVarScope(Ctx->BreakVarScope),
OldContinueVarScope(Ctx->ContinueVarScope) {
@@ -142,6 +131,7 @@ public:
}
private:
+ Compiler<Emitter> *Ctx;
OptLabelTy OldBreakLabel;
OptLabelTy OldContinueLabel;
VariableScope<Emitter> *OldBreakVarScope;
@@ -149,7 +139,7 @@ private:
};
// Sets the context for a switch scope, mapping labels.
-template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
+template <class Emitter> class SwitchScope final {
public:
using LabelTy = typename Compiler<Emitter>::LabelTy;
using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
@@ -157,7 +147,7 @@ public:
SwitchScope(Compiler<Emitter> *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel,
OptLabelTy DefaultLabel)
- : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
+ : Ctx(Ctx), OldBreakLabel(Ctx->BreakLabel),
OldDefaultLabel(this->Ctx->DefaultLabel),
OldCaseLabels(std::move(this->Ctx->CaseLabels)),
OldLabelVarScope(Ctx->BreakVarScope) {
@@ -175,6 +165,7 @@ public:
}
private:
+ Compiler<Emitter> *Ctx;
OptLabelTy OldBreakLabel;
OptLabelTy OldDefaultLabel;
CaseMap OldCaseLabels;
@@ -340,6 +331,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
}
case CK_FloatingToIntegral: {
+ if (!CE->getType()->isIntegralOrEnumerationType())
+ return false;
if (!this->visit(SubExpr))
return false;
PrimType ToT = classifyPrim(CE);
@@ -457,13 +450,17 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
assert(isPtrType(*FromT));
assert(isPtrType(*ToT));
if (FromT == ToT) {
- if (CE->getType()->isVoidPointerType())
+ if (CE->getType()->isVoidPointerType() &&
+ !SubExprTy->isFunctionPointerType()) {
return this->delegate(SubExpr);
+ }
if (!this->visit(SubExpr))
return false;
- if (CE->getType()->isFunctionPointerType())
- return true;
+ if (CE->getType()->isFunctionPointerType() ||
+ SubExprTy->isFunctionPointerType()) {
+ return this->emitFnPtrCast(CE);
+ }
if (FromT == PT_Ptr)
return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), CE);
return true;
@@ -1374,10 +1371,15 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
// BitAdd/BitOr/BitXor/Shl/Shr doesn't support bool type, we need perform the
// integer promotion.
bool NeedIntPromot = ElemT == PT_Bool && (E->isBitwiseOp() || E->isShiftOp());
- QualType PromotTy =
- Ctx.getASTContext().getPromotedIntegerType(Ctx.getASTContext().BoolTy);
- PrimType PromotT = classifyPrim(PromotTy);
- PrimType OpT = NeedIntPromot ? PromotT : ElemT;
+ QualType PromotTy;
+ PrimType PromotT = PT_Bool;
+ PrimType OpT = ElemT;
+ if (NeedIntPromot) {
+ PromotTy =
+ Ctx.getASTContext().getPromotedIntegerType(Ctx.getASTContext().BoolTy);
+ PromotT = classifyPrim(PromotTy);
+ OpT = PromotT;
+ }
auto getElem = [=](unsigned Offset, PrimType ElemT, unsigned Index) {
if (!this->emitGetLocal(PT_Ptr, Offset, E))
@@ -1763,6 +1765,9 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
if (Inits.size() == 1 && E->getType() == Inits[0]->getType())
return this->delegate(Inits[0]);
+ if (!R)
+ return false;
+
auto initPrimitiveField = [=](const Record::Field *FieldToInit,
const Expr *Init, PrimType T,
bool Activate = false) -> bool {
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 3a26342..16f108f 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -21,7 +21,6 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/Basic/TargetInfo.h"
namespace clang {
class QualType;
diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp
index 5b9f445..7403e90 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -21,14 +21,31 @@
using namespace clang;
using namespace clang::interp;
+template <typename T> static constexpr bool needsCtor() {
+ if constexpr (std::is_same_v<T, Integral<8, true>> ||
+ std::is_same_v<T, Integral<8, false>> ||
+ std::is_same_v<T, Integral<16, true>> ||
+ std::is_same_v<T, Integral<16, false>> ||
+ std::is_same_v<T, Integral<32, true>> ||
+ std::is_same_v<T, Integral<32, false>> ||
+ std::is_same_v<T, Integral<64, true>> ||
+ std::is_same_v<T, Integral<64, false>> ||
+ std::is_same_v<T, Boolean>)
+ return false;
+
+ return true;
+}
+
template <typename T>
static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool,
const Descriptor *) {
+ static_assert(needsCtor<T>());
new (Ptr) T();
}
template <typename T>
static void dtorTy(Block *, std::byte *Ptr, const Descriptor *) {
+ static_assert(needsCtor<T>());
reinterpret_cast<T *>(Ptr)->~T();
}
@@ -45,9 +62,11 @@ static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool,
const Descriptor *D) {
new (Ptr) InitMapPtr(std::nullopt);
- Ptr += sizeof(InitMapPtr);
- for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
- new (&reinterpret_cast<T *>(Ptr)[I]) T();
+ if constexpr (needsCtor<T>()) {
+ Ptr += sizeof(InitMapPtr);
+ for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
+ new (&reinterpret_cast<T *>(Ptr)[I]) T();
+ }
}
}
@@ -57,9 +76,12 @@ static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D) {
if (IMP)
IMP = std::nullopt;
- Ptr += sizeof(InitMapPtr);
- for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
- reinterpret_cast<T *>(Ptr)[I].~T();
+
+ if constexpr (needsCtor<T>()) {
+ Ptr += sizeof(InitMapPtr);
+ for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
+ reinterpret_cast<T *>(Ptr)[I].~T();
+ }
}
}
@@ -74,10 +96,14 @@ static void moveArrayTy(Block *, std::byte *Src, std::byte *Dst,
}
Src += sizeof(InitMapPtr);
Dst += sizeof(InitMapPtr);
- for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
- auto *SrcPtr = &reinterpret_cast<T *>(Src)[I];
- auto *DstPtr = &reinterpret_cast<T *>(Dst)[I];
- new (DstPtr) T(std::move(*SrcPtr));
+ if constexpr (!needsCtor<T>()) {
+ std::memcpy(Dst, Src, D->getNumElems() * D->getElemSize());
+ } else {
+ for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
+ auto *SrcPtr = &reinterpret_cast<T *>(Src)[I];
+ auto *DstPtr = &reinterpret_cast<T *>(Dst)[I];
+ new (DstPtr) T(std::move(*SrcPtr));
+ }
}
}
diff --git a/clang/lib/AST/ByteCode/DynamicAllocator.cpp b/clang/lib/AST/ByteCode/DynamicAllocator.cpp
index 169250c..9b8b664 100644
--- a/clang/lib/AST/ByteCode/DynamicAllocator.cpp
+++ b/clang/lib/AST/ByteCode/DynamicAllocator.cpp
@@ -13,6 +13,25 @@
using namespace clang;
using namespace clang::interp;
+// FIXME: There is a peculiar problem with the way we track pointers
+// to blocks and the way we allocate dynamic memory.
+//
+// When we have code like this:
+// while (true) {
+// char *buffer = new char[1024];
+// delete[] buffer;
+// }
+//
+// We have a local variable 'buffer' pointing to the heap allocated memory.
+// When deallocating the memory via delete[], that local variable still
+// points to the memory, which means we will create a DeadBlock for it and move
+// it over to that block, essentially duplicating the allocation. Moving
+// the data is also slow.
+//
+// However, when we actually try to access the allocation after it has been
+// freed, we need the block to still exist (alive or dead) so we can tell
+// that it's a dynamic allocation.
+
DynamicAllocator::~DynamicAllocator() { cleanup(); }
void DynamicAllocator::cleanup() {
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 2602ed7..9a325ab 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -25,7 +25,6 @@
#include "InterpStack.h"
#include "InterpState.h"
#include "MemberPointer.h"
-#include "Opcode.h"
#include "PrimType.h"
#include "Program.h"
#include "State.h"
@@ -1131,8 +1130,9 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
<< LHS.toDiagnosticString(S.getASTContext());
return false;
- } else if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() &&
- LHS.getOffset() == 0) {
+ }
+ if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() &&
+ LHS.getOffset() == 0) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
<< RHS.toDiagnosticString(S.getASTContext());
@@ -1150,8 +1150,9 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_literal_comparison);
return false;
- } else if (const auto *CE = dyn_cast<CallExpr>(E);
- CE && IsOpaqueConstantCall(CE)) {
+ }
+ if (const auto *CE = dyn_cast<CallExpr>(E);
+ CE && IsOpaqueConstantCall(CE)) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_opaque_call_comparison)
<< P.toDiagnosticString(S.getASTContext());
@@ -2681,6 +2682,14 @@ static inline bool CastFixedPointIntegral(InterpState &S, CodePtr OpPC) {
return true;
}
+static inline bool FnPtrCast(InterpState &S, CodePtr OpPC) {
+ const SourceInfo &E = S.Current->getSource(OpPC);
+ S.CCEDiag(E, diag::note_constexpr_invalid_cast)
+ << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
+ << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
+ return true;
+}
+
static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) {
const auto &Ptr = S.Stk.peek<Pointer>();
@@ -3266,7 +3275,8 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
<< static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
return !Fatal;
- } else if (Kind == CastKind::Volatile) {
+ }
+ if (Kind == CastKind::Volatile) {
if (!S.checkingPotentialConstantExpression()) {
const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
if (S.getLangOpts().CPlusPlus)
@@ -3277,7 +3287,8 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
}
return false;
- } else if (Kind == CastKind::Dynamic) {
+ }
+ if (Kind == CastKind::Dynamic) {
assert(!S.getLangOpts().CPlusPlus20);
S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast)
<< diag::ConstexprInvalidCastKind::Dynamic;
diff --git a/clang/lib/AST/ByteCode/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp
index 3010847..32ad07b 100644
--- a/clang/lib/AST/ByteCode/InterpState.cpp
+++ b/clang/lib/AST/ByteCode/InterpState.cpp
@@ -77,27 +77,27 @@ void InterpState::deallocate(Block *B) {
const Descriptor *Desc = B->getDescriptor();
assert(Desc);
+ // The block might have a pointer saved in a field in its data
+ // that points to the block itself. We call the dtor first,
+ // which will destroy all the data but leave InlineDescriptors
+ // intact. If the block THEN still has pointers, we create a
+ // DeadBlock for it.
+ if (B->IsInitialized)
+ B->invokeDtor();
+
if (B->hasPointers()) {
size_t Size = B->getSize();
-
// Allocate a new block, transferring over pointers.
char *Memory =
reinterpret_cast<char *>(std::malloc(sizeof(DeadBlock) + Size));
auto *D = new (Memory) DeadBlock(DeadBlocks, B);
- std::memset(D->B.rawData(), 0, D->B.getSize());
-
- // Move data and metadata from the old block to the new (dead)block.
- if (B->IsInitialized && Desc->MoveFn) {
- Desc->MoveFn(B, B->data(), D->data(), Desc);
- if (Desc->getMetadataSize() > 0)
- std::memcpy(D->rawData(), B->rawData(), Desc->getMetadataSize());
- }
+ // Since the block doesn't hold any actual data anymore, we can just
+ // memcpy() everything over.
+ std::memcpy(D->rawData(), B->rawData(), Desc->getAllocSize());
D->B.IsInitialized = B->IsInitialized;
// We moved the contents over to the DeadBlock.
B->IsInitialized = false;
- } else if (B->IsInitialized) {
- B->invokeDtor();
}
}
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index abfed77..95a4433 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -412,7 +412,7 @@ def CheckDecl : Opcode {
def CheckEnumValue : Opcode {
let Args = [ArgEnumDecl];
- let Types = [FixedSizeIntegralTypeClass];
+ let Types = [IntegralTypeClass];
let HasGroup = 1;
}
@@ -735,6 +735,8 @@ def PtrPtrCast : Opcode {
}
+def FnPtrCast : Opcode;
+
def DecayPtr : Opcode {
let Types = [PtrTypeClass, PtrTypeClass];
let HasGroup = 1;
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 83fcd87..1588be4 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -5988,11 +5988,10 @@ bool clang::IsArmStreamingFunction(const FunctionDecl *FD,
if (FD->hasAttr<ArmLocallyStreamingAttr>())
return true;
- if (const Type *Ty = FD->getType().getTypePtrOrNull())
- if (const auto *FPT = Ty->getAs<FunctionProtoType>())
- if (FPT->getAArch64SMEAttributes() &
- FunctionType::SME_PStateSMEnabledMask)
- return true;
+ assert(!FD->getType().isNull() && "Expected a valid FunctionDecl");
+ if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>())
+ if (FPT->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
+ return true;
return false;
}
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index d85655b..cd9672d 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4233,8 +4233,15 @@ bool Expr::isSameComparisonOperand(const Expr* E1, const Expr* E2) {
// template parameters.
const auto *DRE1 = cast<DeclRefExpr>(E1);
const auto *DRE2 = cast<DeclRefExpr>(E2);
- return DRE1->isPRValue() && DRE2->isPRValue() &&
- DRE1->getDecl() == DRE2->getDecl();
+
+ if (DRE1->getDecl() != DRE2->getDecl())
+ return false;
+
+ if ((DRE1->isPRValue() && DRE2->isPRValue()) ||
+ (DRE1->isLValue() && DRE2->isLValue()))
+ return true;
+
+ return false;
}
case ImplicitCastExprClass: {
// Peel off implicit casts.
@@ -4244,7 +4251,8 @@ bool Expr::isSameComparisonOperand(const Expr* E1, const Expr* E2) {
if (!ICE1 || !ICE2)
return false;
if (ICE1->getCastKind() != ICE2->getCastKind())
- return false;
+ return isSameComparisonOperand(ICE1->IgnoreParenImpCasts(),
+ ICE2->IgnoreParenImpCasts());
E1 = ICE1->getSubExpr()->IgnoreParens();
E2 = ICE2->getSubExpr()->IgnoreParens();
// The final cast must be one of these types.
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9808298..20b7c44 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9741,10 +9741,19 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_AddressSpaceConversion:
if (!Visit(SubExpr))
return false;
- // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are
- // permitted in constant expressions in C++11. Bitcasts from cv void* are
- // also static_casts, but we disallow them as a resolution to DR1312.
- if (!E->getType()->isVoidPointerType()) {
+ if (E->getType()->isFunctionPointerType() ||
+ SubExpr->getType()->isFunctionPointerType()) {
+ // Casting between two function pointer types, or between a function
+ // pointer and an object pointer, is always a reinterpret_cast.
+ CCEDiag(E, diag::note_constexpr_invalid_cast)
+ << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
+ << Info.Ctx.getLangOpts().CPlusPlus;
+ Result.Designator.setInvalid();
+ } else if (!E->getType()->isVoidPointerType()) {
+ // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are
+ // permitted in constant expressions in C++11. Bitcasts from cv void* are
+ // also static_casts, but we disallow them as a resolution to DR1312.
+ //
// In some circumstances, we permit casting from void* to cv1 T*, when the
// actual pointee object is actually a cv2 T.
bool HasValidResult = !Result.InvalidBase && !Result.Designator.Invalid &&
@@ -16849,31 +16858,31 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) {
CheckMemoryLeaks(Info);
}
-static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
+static bool FastEvaluateAsRValue(const Expr *Exp, APValue &Result,
const ASTContext &Ctx, bool &IsConst) {
// Fast-path evaluations of integer literals, since we sometimes see files
// containing vast quantities of these.
if (const auto *L = dyn_cast<IntegerLiteral>(Exp)) {
- Result.Val = APValue(APSInt(L->getValue(),
- L->getType()->isUnsignedIntegerType()));
+ Result =
+ APValue(APSInt(L->getValue(), L->getType()->isUnsignedIntegerType()));
IsConst = true;
return true;
}
if (const auto *L = dyn_cast<CXXBoolLiteralExpr>(Exp)) {
- Result.Val = APValue(APSInt(APInt(1, L->getValue())));
+ Result = APValue(APSInt(APInt(1, L->getValue())));
IsConst = true;
return true;
}
if (const auto *FL = dyn_cast<FloatingLiteral>(Exp)) {
- Result.Val = APValue(FL->getValue());
+ Result = APValue(FL->getValue());
IsConst = true;
return true;
}
if (const auto *L = dyn_cast<CharacterLiteral>(Exp)) {
- Result.Val = APValue(Ctx.MakeIntValue(L->getValue(), L->getType()));
+ Result = APValue(Ctx.MakeIntValue(L->getValue(), L->getType()));
IsConst = true;
return true;
}
@@ -16882,7 +16891,7 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
if (CE->hasAPValueResult()) {
APValue APV = CE->getAPValueResult();
if (!APV.isLValue()) {
- Result.Val = std::move(APV);
+ Result = std::move(APV);
IsConst = true;
return true;
}
@@ -16912,7 +16921,7 @@ static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result,
const ASTContext &Ctx, EvalInfo &Info) {
assert(!E->isValueDependent());
bool IsConst;
- if (FastEvaluateAsRValue(E, Result, Ctx, IsConst))
+ if (FastEvaluateAsRValue(E, Result.Val, Ctx, IsConst))
return IsConst;
return EvaluateAsRValue(Info, E, Result.Val);
@@ -17069,7 +17078,8 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx,
assert(!isValueDependent() &&
"Expression evaluator can't be called on a dependent expression.");
bool IsConst;
- if (FastEvaluateAsRValue(this, Result, Ctx, IsConst) && Result.Val.hasValue())
+ if (FastEvaluateAsRValue(this, Result.Val, Ctx, IsConst) &&
+ Result.Val.hasValue())
return true;
ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsConstantExpr");
@@ -17284,7 +17294,7 @@ void Expr::EvaluateForOverflow(const ASTContext &Ctx) const {
ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateForOverflow");
bool IsConst;
EvalResult EVResult;
- if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) {
+ if (!FastEvaluateAsRValue(this, EVResult.Val, Ctx, IsConst)) {
EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects);
Info.CheckingForUndefinedBehavior = true;
(void)::EvaluateAsRValue(Info, this, EVResult.Val);
@@ -17303,8 +17313,7 @@ bool Expr::EvalResult::isGlobalLValue() const {
/// comma, etc
// CheckICE - This function does the fundamental ICE checking: the returned
-// ICEDiag contains an ICEKind indicating whether the expression is an ICE,
-// and a (possibly null) SourceLocation indicating the location of the problem.
+// ICEDiag contains an ICEKind indicating whether the expression is an ICE.
//
// Note that to reduce code duplication, this helper does no evaluation
// itself; the caller checks whether the expression is evaluatable, and
@@ -17768,60 +17777,51 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
/// Evaluate an expression as a C++11 integral constant expression.
static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx,
const Expr *E,
- llvm::APSInt *Value,
- SourceLocation *Loc) {
- if (!E->getType()->isIntegralOrUnscopedEnumerationType()) {
- if (Loc) *Loc = E->getExprLoc();
+ llvm::APSInt *Value) {
+ if (!E->getType()->isIntegralOrUnscopedEnumerationType())
return false;
- }
APValue Result;
- if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc))
+ if (!E->isCXX11ConstantExpr(Ctx, &Result))
return false;
- if (!Result.isInt()) {
- if (Loc) *Loc = E->getExprLoc();
+ if (!Result.isInt())
return false;
- }
if (Value) *Value = Result.getInt();
return true;
}
-bool Expr::isIntegerConstantExpr(const ASTContext &Ctx,
- SourceLocation *Loc) const {
+bool Expr::isIntegerConstantExpr(const ASTContext &Ctx) const {
assert(!isValueDependent() &&
"Expression evaluator can't be called on a dependent expression.");
ExprTimeTraceScope TimeScope(this, Ctx, "isIntegerConstantExpr");
if (Ctx.getLangOpts().CPlusPlus11)
- return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc);
+ return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr);
ICEDiag D = CheckICE(this, Ctx);
- if (D.Kind != IK_ICE) {
- if (Loc) *Loc = D.Loc;
+ if (D.Kind != IK_ICE)
return false;
- }
return true;
}
std::optional<llvm::APSInt>
-Expr::getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc) const {
+Expr::getIntegerConstantExpr(const ASTContext &Ctx) const {
if (isValueDependent()) {
// Expression evaluator can't succeed on a dependent expression.
return std::nullopt;
}
- APSInt Value;
-
if (Ctx.getLangOpts().CPlusPlus11) {
- if (EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc))
+ APSInt Value;
+ if (EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value))
return Value;
return std::nullopt;
}
- if (!isIntegerConstantExpr(Ctx, Loc))
+ if (!isIntegerConstantExpr(Ctx))
return std::nullopt;
// The only possible side-effects here are due to UB discovered in the
@@ -17846,8 +17846,7 @@ bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const {
return CheckICE(this, Ctx).Kind == IK_ICE;
}
-bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result,
- SourceLocation *Loc) const {
+bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result) const {
assert(!isValueDependent() &&
"Expression evaluator can't be called on a dependent expression.");
@@ -17855,28 +17854,27 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result,
// issues.
assert(Ctx.getLangOpts().CPlusPlus);
+ bool IsConst;
+ APValue Scratch;
+ if (FastEvaluateAsRValue(this, Scratch, Ctx, IsConst) && Scratch.hasValue()) {
+ if (Result)
+ *Result = Scratch;
+ return true;
+ }
+
// Build evaluation settings.
Expr::EvalStatus Status;
SmallVector<PartialDiagnosticAt, 8> Diags;
Status.Diag = &Diags;
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression);
- APValue Scratch;
bool IsConstExpr =
::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) &&
// FIXME: We don't produce a diagnostic for this, but the callers that
// call us on arbitrary full-expressions should generally not care.
Info.discardCleanups() && !Status.HasSideEffects;
- if (!Diags.empty()) {
- IsConstExpr = false;
- if (Loc) *Loc = Diags[0].first;
- } else if (!IsConstExpr) {
- // FIXME: This shouldn't happen.
- if (Loc) *Loc = getExprLoc();
- }
-
- return IsConstExpr;
+ return IsConstExpr && Diags.empty();
}
bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index bc47e05..e6ea0ad 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1298,8 +1298,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
Name += "<unnamed-type-";
Name += TND->getName();
} else if (isa<EnumDecl>(TD) &&
- cast<EnumDecl>(TD)->enumerator_begin() !=
- cast<EnumDecl>(TD)->enumerator_end()) {
+ !cast<EnumDecl>(TD)->enumerators().empty()) {
// Anonymous non-empty enums mangle in the first enumerator.
auto *ED = cast<EnumDecl>(TD);
Name += "<unnamed-enum-";
diff --git a/clang/lib/Analysis/RetainSummaryManager.cpp b/clang/lib/Analysis/RetainSummaryManager.cpp
index 987f894..688efe4 100644
--- a/clang/lib/Analysis/RetainSummaryManager.cpp
+++ b/clang/lib/Analysis/RetainSummaryManager.cpp
@@ -147,8 +147,7 @@ static bool isSubclass(const Decl *D,
static bool isExactClass(const Decl *D, StringRef ClassName) {
using namespace ast_matchers;
- DeclarationMatcher sameClassM =
- cxxRecordDecl(hasName(std::string(ClassName)));
+ DeclarationMatcher sameClassM = cxxRecordDecl(hasName(ClassName));
return !(match(sameClassM, *D, D->getASTContext()).empty());
}
diff --git a/clang/lib/Basic/Cuda.cpp b/clang/lib/Basic/Cuda.cpp
index 53b36d3..dc81b71 100644
--- a/clang/lib/Basic/Cuda.cpp
+++ b/clang/lib/Basic/Cuda.cpp
@@ -44,6 +44,7 @@ static const CudaVersionMapEntry CudaNameVersionMap[] = {
CUDA_ENTRY(12, 5),
CUDA_ENTRY(12, 6),
CUDA_ENTRY(12, 8),
+ CUDA_ENTRY(12, 9),
{"", CudaVersion::NEW, llvm::VersionTuple(std::numeric_limits<int>::max())},
{"unknown", CudaVersion::UNKNOWN, {}} // End of list tombstone.
};
@@ -119,6 +120,11 @@ CudaVersion MinVersionForOffloadArch(OffloadArch A) {
case OffloadArch::SM_120:
case OffloadArch::SM_120a:
return CudaVersion::CUDA_128;
+ case OffloadArch::SM_103:
+ case OffloadArch::SM_103a:
+ case OffloadArch::SM_121:
+ case OffloadArch::SM_121a:
+ return CudaVersion::CUDA_129;
default:
llvm_unreachable("invalid enum");
}
diff --git a/clang/lib/Basic/OffloadArch.cpp b/clang/lib/Basic/OffloadArch.cpp
index dce9ffa..4348178 100644
--- a/clang/lib/Basic/OffloadArch.cpp
+++ b/clang/lib/Basic/OffloadArch.cpp
@@ -33,8 +33,12 @@ static const OffloadArchToStringMap ArchNames[] = {
SM(100a), // Blackwell
SM(101), // Blackwell
SM(101a), // Blackwell
+ SM(103), // Blackwell
+ SM(103a), // Blackwell
SM(120), // Blackwell
SM(120a), // Blackwell
+ SM(121), // Blackwell
+ SM(121a), // Blackwell
GFX(600), // gfx600
GFX(601), // gfx601
GFX(602), // gfx602
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index b2b1488..343c26e 100644
--- a/clang/lib/Basic/SourceManager.cpp
+++ b/clang/lib/Basic/SourceManager.cpp
@@ -2366,23 +2366,21 @@ size_t SourceManager::getDataStructureSizes() const {
SourceManagerForFile::SourceManagerForFile(StringRef FileName,
StringRef Content) {
- // This is referenced by `FileMgr` and will be released by `FileMgr` when it
- // is deleted.
- IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
- new llvm::vfs::InMemoryFileSystem);
+ auto InMemoryFileSystem =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
InMemoryFileSystem->addFile(
FileName, 0,
llvm::MemoryBuffer::getMemBuffer(Content, FileName,
/*RequiresNullTerminator=*/false));
// This is passed to `SM` as reference, so the pointer has to be referenced
// in `Environment` so that `FileMgr` can out-live this function scope.
- FileMgr =
- std::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem);
+ FileMgr = std::make_unique<FileManager>(FileSystemOptions(),
+ std::move(InMemoryFileSystem));
DiagOpts = std::make_unique<DiagnosticOptions>();
// This is passed to `SM` as reference, so the pointer has to be referenced
// by `Environment` due to the same reason above.
- Diagnostics = std::make_unique<DiagnosticsEngine>(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), *DiagOpts);
+ Diagnostics =
+ std::make_unique<DiagnosticsEngine>(DiagnosticIDs::create(), *DiagOpts);
SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
FileEntryRef FE = llvm::cantFail(FileMgr->getFileRef(FileName));
FileID ID =
diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp
index 6bec2fa..75fdf38 100644
--- a/clang/lib/Basic/Targets/ARM.cpp
+++ b/clang/lib/Basic/Targets/ARM.cpp
@@ -133,19 +133,24 @@ void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
}
void ARMTargetInfo::setAtomic() {
- // when triple does not specify a sub arch,
- // then we are not using inline atomics
- bool ShouldUseInlineAtomic =
- (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) ||
- (ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7);
- // Cortex M does not support 8 byte atomics, while general Thumb2 does.
if (ArchProfile == llvm::ARM::ProfileKind::M) {
+ // M-class only ever supports 32-bit atomics. Cortex-M0 doesn't have
+ // any atomics.
MaxAtomicPromoteWidth = 32;
- if (ShouldUseInlineAtomic)
+ if (ArchVersion >= 7)
MaxAtomicInlineWidth = 32;
} else {
+ // A-class targets have up to 64-bit atomics.
+ //
+ // On Linux, 64-bit atomics are always available through kernel helpers
+ // (which are lock-free). Otherwise, atomics are available on v6 or later.
+ //
+ // (Thumb doesn't matter; for Thumbv6, we just use a library call which
+ // switches out of Thumb mode.)
+ //
+ // This should match setMaxAtomicSizeInBitsSupported() in the backend.
MaxAtomicPromoteWidth = 64;
- if (ShouldUseInlineAtomic)
+ if (getTriple().getOS() == llvm::Triple::Linux || ArchVersion >= 6)
MaxAtomicInlineWidth = 64;
}
}
diff --git a/clang/lib/Basic/Targets/NVPTX.cpp b/clang/lib/Basic/Targets/NVPTX.cpp
index 54b39fd..79995cc 100644
--- a/clang/lib/Basic/Targets/NVPTX.cpp
+++ b/clang/lib/Basic/Targets/NVPTX.cpp
@@ -295,10 +295,16 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
return "1000";
case OffloadArch::SM_101:
case OffloadArch::SM_101a:
- return "1010";
+ return "1010";
+ case OffloadArch::SM_103:
+ case OffloadArch::SM_103a:
+ return "1030";
case OffloadArch::SM_120:
case OffloadArch::SM_120a:
- return "1200";
+ return "1200";
+ case OffloadArch::SM_121:
+ case OffloadArch::SM_121a:
+ return "1210";
}
llvm_unreachable("unhandled OffloadArch");
}();
@@ -307,7 +313,9 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
case OffloadArch::SM_90a:
case OffloadArch::SM_100a:
case OffloadArch::SM_101a:
+ case OffloadArch::SM_103a:
case OffloadArch::SM_120a:
+ case OffloadArch::SM_121a:
Builder.defineMacro("__CUDA_ARCH_FEAT_SM" + CUDAArchCode.drop_back() + "_ALL", "1");
break;
default:
diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp
index e362350e..55ffe1d 100644
--- a/clang/lib/Basic/Targets/WebAssembly.cpp
+++ b/clang/lib/Basic/Targets/WebAssembly.cpp
@@ -59,12 +59,12 @@ bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
.Case("exception-handling", HasExceptionHandling)
.Case("extended-const", HasExtendedConst)
.Case("fp16", HasFP16)
+ .Case("gc", HasGC)
.Case("multimemory", HasMultiMemory)
.Case("multivalue", HasMultivalue)
.Case("mutable-globals", HasMutableGlobals)
.Case("nontrapping-fptoint", HasNontrappingFPToInt)
.Case("reference-types", HasReferenceTypes)
- .Case("gc", HasGC)
.Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)
.Case("sign-ext", HasSignExt)
.Case("simd128", SIMDLevel >= SIMD128)
@@ -99,6 +99,8 @@ void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__wasm_multimemory__");
if (HasFP16)
Builder.defineMacro("__wasm_fp16__");
+ if (HasGC)
+ Builder.defineMacro("__wasm_gc__");
if (HasMultivalue)
Builder.defineMacro("__wasm_multivalue__");
if (HasMutableGlobals)
@@ -107,8 +109,6 @@ void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__wasm_nontrapping_fptoint__");
if (HasReferenceTypes)
Builder.defineMacro("__wasm_reference_types__");
- if (HasGC)
- Builder.defineMacro("__wasm_gc__");
if (SIMDLevel >= RelaxedSIMD)
Builder.defineMacro("__wasm_relaxed_simd__");
if (HasSignExt)
@@ -194,6 +194,7 @@ bool WebAssemblyTargetInfo::initFeatureMap(
Features["exception-handling"] = true;
Features["extended-const"] = true;
Features["fp16"] = true;
+ Features["gc"] = true;
Features["multimemory"] = true;
Features["tail-call"] = true;
Features["wide-arithmetic"] = true;
@@ -270,6 +271,14 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
HasFP16 = false;
continue;
}
+ if (Feature == "+gc") {
+ HasGC = true;
+ continue;
+ }
+ if (Feature == "-gc") {
+ HasGC = false;
+ continue;
+ }
if (Feature == "+multimemory") {
HasMultiMemory = true;
continue;
@@ -310,14 +319,6 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
HasReferenceTypes = false;
continue;
}
- if (Feature == "+gc") {
- HasGC = true;
- continue;
- }
- if (Feature == "-gc") {
- HasGC = false;
- continue;
- }
if (Feature == "+relaxed-simd") {
SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);
continue;
diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h
index c47c8cc..eba7422 100644
--- a/clang/lib/Basic/Targets/WebAssembly.h
+++ b/clang/lib/Basic/Targets/WebAssembly.h
@@ -64,12 +64,12 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
bool HasExceptionHandling = false;
bool HasExtendedConst = false;
bool HasFP16 = false;
+ bool HasGC = false;
bool HasMultiMemory = false;
bool HasMultivalue = false;
bool HasMutableGlobals = false;
bool HasNontrappingFPToInt = false;
bool HasReferenceTypes = false;
- bool HasGC = false;
bool HasSignExt = false;
bool HasTailCall = false;
bool HasWideArithmetic = false;
diff --git a/clang/lib/CIR/CodeGen/Address.h b/clang/lib/CIR/CodeGen/Address.h
index 6f76c3e..6c927e9 100644
--- a/clang/lib/CIR/CodeGen/Address.h
+++ b/clang/lib/CIR/CodeGen/Address.h
@@ -101,6 +101,17 @@ public:
}
clang::CharUnits getAlignment() const { return alignment; }
+
+ /// Get the operation which defines this address.
+ mlir::Operation *getDefiningOp() const {
+ if (!isValid())
+ return nullptr;
+ return getPointer().getDefiningOp();
+ }
+
+ template <typename OpTy> OpTy getDefiningOp() const {
+ return mlir::dyn_cast_or_null<OpTy>(getDefiningOp());
+ }
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.h b/clang/lib/CIR/CodeGen/CIRGenCall.h
index a78956b..28576a1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.h
@@ -137,7 +137,7 @@ private:
/// A data-flow flag to make sure getRValue and/or copyInto are not
/// called twice for duplicated IR emission.
- mutable bool isUsed;
+ [[maybe_unused]] mutable bool isUsed;
public:
clang::QualType ty;
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 50cca0e..72b9d17 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -349,12 +349,16 @@ void CIRGenFunction::emitCXXAggrConstructorCall(
// doesn't happen, but it's not clear that it's worth it.
// Optimize for a constant count.
- auto constantCount = dyn_cast<cir::ConstantOp>(numElements.getDefiningOp());
- if (constantCount) {
- auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());
- // Just skip out if the constant count is zero.
- if (constIntAttr && constIntAttr.getUInt() == 0)
- return;
+ if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
+ if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>()) {
+ // Just skip out if the constant count is zero.
+ if (constIntAttr.getUInt() == 0)
+ return;
+ // Otherwise, emit the check.
+ }
+
+ if (constantCount.use_empty())
+ constantCount.erase();
} else {
// Otherwise, emit the check.
cgm.errorNYI(e->getSourceRange(), "dynamic-length array expression");
@@ -417,9 +421,6 @@ void CIRGenFunction::emitCXXAggrConstructorCall(
builder.create<cir::YieldOp>(loc);
});
}
-
- if (constantCount.use_empty())
- constantCount.erase();
}
void CIRGenFunction::emitDelegateCXXConstructorCall(
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index 6527fb5..78d375c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -24,7 +24,8 @@ using namespace clang;
using namespace clang::CIRGen;
CIRGenFunction::AutoVarEmission
-CIRGenFunction::emitAutoVarAlloca(const VarDecl &d) {
+CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,
+ mlir::OpBuilder::InsertPoint ip) {
QualType ty = d.getType();
if (ty.getAddressSpace() != LangAS::Default)
cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: address space");
@@ -50,7 +51,8 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d) {
// A normal fixed sized variable becomes an alloca in the entry block,
mlir::Type allocaTy = convertTypeForMem(ty);
// Create the temp alloca and declare variable using it.
- address = createTempAlloca(allocaTy, alignment, loc, d.getName());
+ address = createTempAlloca(allocaTy, alignment, loc, d.getName(),
+ /*arraySize=*/nullptr, /*alloca=*/nullptr, ip);
declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()), alignment);
emission.Addr = address;
@@ -156,7 +158,7 @@ void CIRGenFunction::emitAutoVarInit(
// out of it while trying to build the expression, mark it as such.
mlir::Value val = lv.getAddress().getPointer();
assert(val && "Should have an address");
- auto allocaOp = dyn_cast_or_null<cir::AllocaOp>(val.getDefiningOp());
+ auto allocaOp = val.getDefiningOp<cir::AllocaOp>();
assert(allocaOp && "Address should come straight out of the alloca");
if (!allocaOp.use_empty())
@@ -410,7 +412,8 @@ void CIRGenFunction::emitStaticVarDecl(const VarDecl &d,
// TODO(cir): we should have a way to represent global ops as values without
// having to emit a get global op. Sometimes these emissions are not used.
mlir::Value addr = builder.createGetGlobal(globalOp);
- auto getAddrOp = mlir::cast<cir::GetGlobalOp>(addr.getDefiningOp());
+ auto getAddrOp = addr.getDefiningOp<cir::GetGlobalOp>();
+ assert(getAddrOp && "expected cir::GetGlobalOp");
CharUnits alignment = getContext().getDeclAlign(&d);
@@ -520,7 +523,7 @@ void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d,
llvm_unreachable("bad evaluation kind");
}
-void CIRGenFunction::emitDecl(const Decl &d) {
+void CIRGenFunction::emitDecl(const Decl &d, bool evaluateConditionDecl) {
switch (d.getKind()) {
case Decl::BuiltinTemplate:
case Decl::TranslationUnit:
@@ -608,11 +611,14 @@ void CIRGenFunction::emitDecl(const Decl &d) {
case Decl::UsingDirective: // using namespace X; [C++]
assert(!cir::MissingFeatures::generateDebugInfo());
return;
- case Decl::Var: {
+ case Decl::Var:
+ case Decl::Decomposition: {
const VarDecl &vd = cast<VarDecl>(d);
assert(vd.isLocalVarDecl() &&
"Should not see file-scope variables inside a function!");
emitVarDecl(vd);
+ if (evaluateConditionDecl)
+ maybeEmitDeferredVarDeclInit(&vd);
return;
}
case Decl::OpenACCDeclare:
@@ -632,7 +638,6 @@ void CIRGenFunction::emitDecl(const Decl &d) {
case Decl::ImplicitConceptSpecialization:
case Decl::TopLevelStmt:
case Decl::UsingPack:
- case Decl::Decomposition: // This could be moved to join Decl::Var
case Decl::OMPDeclareReduction:
case Decl::OMPDeclareMapper:
cgm.errorNYI(d.getSourceRange(),
@@ -649,6 +654,27 @@ void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,
assert(!cir::MissingFeatures::sanitizers());
}
+namespace {
+struct DestroyObject final : EHScopeStack::Cleanup {
+ DestroyObject(Address addr, QualType type,
+ CIRGenFunction::Destroyer *destroyer)
+ : addr(addr), type(type), destroyer(destroyer) {}
+
+ Address addr;
+ QualType type;
+ CIRGenFunction::Destroyer *destroyer;
+
+ void emit(CIRGenFunction &cgf) override {
+ cgf.emitDestroy(addr, type, destroyer);
+ }
+};
+} // namespace
+
+void CIRGenFunction::pushDestroy(CleanupKind cleanupKind, Address addr,
+ QualType type, Destroyer *destroyer) {
+ pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
+}
+
/// Destroys all the elements of the given array, beginning from last to first.
/// The array cannot be zero-length.
///
@@ -736,22 +762,6 @@ CIRGenFunction::getDestroyer(QualType::DestructionKind kind) {
llvm_unreachable("Unknown DestructionKind");
}
-namespace {
-struct DestroyObject final : EHScopeStack::Cleanup {
- DestroyObject(Address addr, QualType type,
- CIRGenFunction::Destroyer *destroyer)
- : addr(addr), type(type), destroyer(destroyer) {}
-
- Address addr;
- QualType type;
- CIRGenFunction::Destroyer *destroyer;
-
- void emit(CIRGenFunction &cgf) override {
- cgf.emitDestroy(addr, type, destroyer);
- }
-};
-} // namespace
-
/// Enter a destroy cleanup for the given local variable.
void CIRGenFunction::emitAutoVarTypeCleanup(
const CIRGenFunction::AutoVarEmission &emission,
@@ -797,3 +807,11 @@ void CIRGenFunction::emitAutoVarTypeCleanup(
assert(!cir::MissingFeatures::ehCleanupFlags());
ehStack.pushCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
}
+
+void CIRGenFunction::maybeEmitDeferredVarDeclInit(const VarDecl *vd) {
+ if (auto *dd = dyn_cast_if_present<DecompositionDecl>(vd)) {
+ for (auto *b : dd->flat_bindings())
+ if (auto *hd = b->getHoldingVar())
+ emitVarDecl(*hd);
+ }
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index c18498f..cd37a2b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -303,8 +303,7 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
// Update the alloca with more info on initialization.
assert(addr.getPointer() && "expected pointer to exist");
- auto srcAlloca =
- dyn_cast_or_null<cir::AllocaOp>(addr.getPointer().getDefiningOp());
+ auto srcAlloca = addr.getDefiningOp<cir::AllocaOp>();
if (currVarDecl && srcAlloca) {
const VarDecl *vd = currVarDecl;
assert(vd && "VarDecl expected");
@@ -584,6 +583,15 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
return lv;
}
+ if (const auto *bd = dyn_cast<BindingDecl>(nd)) {
+ if (e->refersToEnclosingVariableOrCapture()) {
+ assert(!cir::MissingFeatures::lambdaCaptures());
+ cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: lambda captures");
+ return LValue();
+ }
+ return emitLValue(bd->getBinding());
+ }
+
cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");
return LValue();
}
@@ -626,10 +634,8 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) {
// Tag 'load' with deref attribute.
// FIXME: This misses some derefence cases and has problematic interactions
// with other operators.
- if (auto loadOp =
- dyn_cast<cir::LoadOp>(addr.getPointer().getDefiningOp())) {
+ if (auto loadOp = addr.getDefiningOp<cir::LoadOp>())
loadOp.setIsDerefAttr(mlir::UnitAttr::get(&getMLIRContext()));
- }
LValue lv = makeAddrLValue(addr, t, baseInfo);
assert(!cir::MissingFeatures::addressSpace());
@@ -712,8 +718,8 @@ static const Expr *getSimpleArrayDecayOperand(const Expr *e) {
static cir::IntAttr getConstantIndexOrNull(mlir::Value idx) {
// TODO(cir): should we consider using MLIRs IndexType instead of IntegerAttr?
- if (auto constantOp = dyn_cast<cir::ConstantOp>(idx.getDefiningOp()))
- return mlir::dyn_cast<cir::IntAttr>(constantOp.getValue());
+ if (auto constantOp = idx.getDefiningOp<cir::ConstantOp>())
+ return constantOp.getValueAttr<cir::IntAttr>();
return {};
}
@@ -721,8 +727,7 @@ static CharUnits getArrayElementAlign(CharUnits arrayAlign, mlir::Value idx,
CharUnits eltSize) {
// If we have a constant index, we can use the exact offset of the
// element we're accessing.
- const cir::IntAttr constantIdx = getConstantIndexOrNull(idx);
- if (constantIdx) {
+ if (const cir::IntAttr constantIdx = getConstantIndexOrNull(idx)) {
const CharUnits offset = constantIdx.getValue().getZExtValue() * eltSize;
return arrayAlign.alignmentAtOffset(offset);
}
@@ -1096,6 +1101,151 @@ void CIRGenFunction::emitAnyExprToMem(const Expr *e, Address location,
llvm_unreachable("bad evaluation kind");
}
+static Address createReferenceTemporary(CIRGenFunction &cgf,
+ const MaterializeTemporaryExpr *m,
+ const Expr *inner) {
+ // TODO(cir): cgf.getTargetHooks();
+ switch (m->getStorageDuration()) {
+ case SD_FullExpression:
+ case SD_Automatic: {
+ QualType ty = inner->getType();
+
+ assert(!cir::MissingFeatures::mergeAllConstants());
+
+ // The temporary memory should be created in the same scope as the extending
+ // declaration of the temporary materialization expression.
+ cir::AllocaOp extDeclAlloca;
+ if (const ValueDecl *extDecl = m->getExtendingDecl()) {
+ auto extDeclAddrIter = cgf.localDeclMap.find(extDecl);
+ if (extDeclAddrIter != cgf.localDeclMap.end())
+ extDeclAlloca = extDeclAddrIter->second.getDefiningOp<cir::AllocaOp>();
+ }
+ mlir::OpBuilder::InsertPoint ip;
+ if (extDeclAlloca)
+ ip = {extDeclAlloca->getBlock(), extDeclAlloca->getIterator()};
+ return cgf.createMemTemp(ty, cgf.getLoc(m->getSourceRange()),
+ cgf.getCounterRefTmpAsString(), /*alloca=*/nullptr,
+ ip);
+ }
+ case SD_Thread:
+ case SD_Static: {
+ cgf.cgm.errorNYI(
+ m->getSourceRange(),
+ "createReferenceTemporary: static/thread storage duration");
+ return Address::invalid();
+ }
+
+ case SD_Dynamic:
+ llvm_unreachable("temporary can't have dynamic storage duration");
+ }
+ llvm_unreachable("unknown storage duration");
+}
+
+static void pushTemporaryCleanup(CIRGenFunction &cgf,
+ const MaterializeTemporaryExpr *m,
+ const Expr *e, Address referenceTemporary) {
+ // Objective-C++ ARC:
+ // If we are binding a reference to a temporary that has ownership, we
+ // need to perform retain/release operations on the temporary.
+ //
+ // FIXME(ogcg): This should be looking at e, not m.
+ if (m->getType().getObjCLifetime()) {
+ cgf.cgm.errorNYI(e->getSourceRange(), "pushTemporaryCleanup: ObjCLifetime");
+ return;
+ }
+
+ CXXDestructorDecl *referenceTemporaryDtor = nullptr;
+ if (const clang::RecordType *rt = e->getType()
+ ->getBaseElementTypeUnsafe()
+ ->getAs<clang::RecordType>()) {
+ // Get the destructor for the reference temporary.
+ auto *classDecl = cast<CXXRecordDecl>(rt->getDecl());
+ if (!classDecl->hasTrivialDestructor())
+ referenceTemporaryDtor = classDecl->getDestructor();
+ }
+
+ if (!referenceTemporaryDtor)
+ return;
+
+ // Call the destructor for the temporary.
+ switch (m->getStorageDuration()) {
+ case SD_Static:
+ case SD_Thread:
+ cgf.cgm.errorNYI(e->getSourceRange(),
+ "pushTemporaryCleanup: static/thread storage duration");
+ return;
+
+ case SD_FullExpression:
+ cgf.pushDestroy(NormalAndEHCleanup, referenceTemporary, e->getType(),
+ CIRGenFunction::destroyCXXObject);
+ break;
+
+ case SD_Automatic:
+ cgf.cgm.errorNYI(e->getSourceRange(),
+ "pushTemporaryCleanup: automatic storage duration");
+ break;
+
+ case SD_Dynamic:
+ llvm_unreachable("temporary cannot have dynamic storage duration");
+ }
+}
+
+LValue CIRGenFunction::emitMaterializeTemporaryExpr(
+ const MaterializeTemporaryExpr *m) {
+ const Expr *e = m->getSubExpr();
+
+ assert((!m->getExtendingDecl() || !isa<VarDecl>(m->getExtendingDecl()) ||
+ !cast<VarDecl>(m->getExtendingDecl())->isARCPseudoStrong()) &&
+ "Reference should never be pseudo-strong!");
+
+ // FIXME: ideally this would use emitAnyExprToMem, however, we cannot do so
+ // as that will cause the lifetime adjustment to be lost for ARC
+ auto ownership = m->getType().getObjCLifetime();
+ if (ownership != Qualifiers::OCL_None &&
+ ownership != Qualifiers::OCL_ExplicitNone) {
+ cgm.errorNYI(e->getSourceRange(),
+ "emitMaterializeTemporaryExpr: ObjCLifetime");
+ return {};
+ }
+
+ SmallVector<const Expr *, 2> commaLHSs;
+ SmallVector<SubobjectAdjustment, 2> adjustments;
+ e = e->skipRValueSubobjectAdjustments(commaLHSs, adjustments);
+
+ for (const Expr *ignored : commaLHSs)
+ emitIgnoredExpr(ignored);
+
+ if (isa<OpaqueValueExpr>(e)) {
+ cgm.errorNYI(e->getSourceRange(),
+ "emitMaterializeTemporaryExpr: OpaqueValueExpr");
+ return {};
+ }
+
+ // Create and initialize the reference temporary.
+ Address object = createReferenceTemporary(*this, m, e);
+
+ if (auto var = object.getPointer().getDefiningOp<cir::GlobalOp>()) {
+ // TODO(cir): add something akin to stripPointerCasts() to ptr above
+ cgm.errorNYI(e->getSourceRange(), "emitMaterializeTemporaryExpr: GlobalOp");
+ return {};
+ } else {
+ assert(!cir::MissingFeatures::emitLifetimeMarkers());
+ emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);
+ }
+ pushTemporaryCleanup(*this, m, e, object);
+
+ // Perform derived-to-base casts and/or field accesses, to get from the
+ // temporary object we created (and, potentially, for which we extended
+ // the lifetime) to the subobject we're binding the reference to.
+ if (!adjustments.empty()) {
+ cgm.errorNYI(e->getSourceRange(),
+ "emitMaterializeTemporaryExpr: Adjustments");
+ return {};
+ }
+
+ return makeAddrLValue(object, m->getType(), AlignmentSource::Decl);
+}
+
LValue CIRGenFunction::emitCompoundLiteralLValue(const CompoundLiteralExpr *e) {
if (e->isFileScope()) {
cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope");
@@ -1472,9 +1622,10 @@ Address CIRGenFunction::emitArrayToPointerDecay(const Expr *e) {
if (e->getType()->isVariableArrayType())
return addr;
- auto pointeeTy = mlir::cast<cir::ArrayType>(lvalueAddrTy.getPointee());
+ [[maybe_unused]] auto pointeeTy =
+ mlir::cast<cir::ArrayType>(lvalueAddrTy.getPointee());
- mlir::Type arrayTy = convertType(e->getType());
+ [[maybe_unused]] mlir::Type arrayTy = convertType(e->getType());
assert(mlir::isa<cir::ArrayType>(arrayTy) && "expected array");
assert(pointeeTy == arrayTy);
@@ -1852,9 +2003,9 @@ cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
const Twine &name,
mlir::Value arraySize,
bool insertIntoFnEntryBlock) {
- return cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(),
- insertIntoFnEntryBlock, arraySize)
- .getDefiningOp());
+ return mlir::cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(),
+ insertIntoFnEntryBlock, arraySize)
+ .getDefiningOp());
}
/// This creates an alloca and inserts it into the provided insertion point
@@ -1864,7 +2015,7 @@ cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
mlir::OpBuilder::InsertPoint ip,
mlir::Value arraySize) {
assert(ip.isSet() && "Insertion point is not set");
- return cast<cir::AllocaOp>(
+ return mlir::cast<cir::AllocaOp>(
emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize)
.getDefiningOp());
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index a09d739..3aa170e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -91,6 +91,14 @@ public:
}
mlir::Value VisitUnaryDeref(const Expr *e);
+
+ mlir::Value VisitUnaryPlus(const UnaryOperator *e);
+
+ mlir::Value VisitPlusMinus(const UnaryOperator *e, cir::UnaryOpKind kind,
+ QualType promotionType);
+
+ mlir::Value VisitUnaryMinus(const UnaryOperator *e);
+
mlir::Value VisitUnaryNot(const UnaryOperator *e);
struct BinOpInfo {
@@ -110,6 +118,7 @@ public:
mlir::Value emitBinAdd(const BinOpInfo &op);
mlir::Value emitBinSub(const BinOpInfo &op);
+ mlir::Value emitBinMul(const BinOpInfo &op);
QualType getPromotionType(QualType ty, bool isDivOpCode = false) {
if (auto *complexTy = ty->getAs<ComplexType>()) {
@@ -142,16 +151,20 @@ public:
HANDLEBINOP(Add)
HANDLEBINOP(Sub)
+ HANDLEBINOP(Mul)
#undef HANDLEBINOP
};
} // namespace
+#ifndef NDEBUG
+// Only used in asserts
static const ComplexType *getComplexType(QualType type) {
type = type.getCanonicalType();
if (const ComplexType *comp = dyn_cast<ComplexType>(type))
return comp;
return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
}
+#endif // NDEBUG
LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
mlir::Value &value) {
@@ -282,6 +295,41 @@ mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
llvm_unreachable("unknown cast resulting in complex value");
}
+mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) {
+ QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
+ mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Plus, promotionTy);
+ if (!promotionTy.isNull()) {
+ cgf.cgm.errorNYI("ComplexExprEmitter::VisitUnaryPlus emitUnPromotedValue");
+ return {};
+ }
+ return result;
+}
+
+mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e,
+ cir::UnaryOpKind kind,
+ QualType promotionType) {
+ assert(kind == cir::UnaryOpKind::Plus ||
+ kind == cir::UnaryOpKind::Minus &&
+ "Invalid UnaryOp kind for ComplexType Plus or Minus");
+
+ mlir::Value op;
+ if (!promotionType.isNull())
+ op = cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType);
+ else
+ op = Visit(e->getSubExpr());
+ return builder.createUnaryOp(cgf.getLoc(e->getExprLoc()), kind, op);
+}
+
+mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) {
+ QualType promotionTy = getPromotionType(e->getSubExpr()->getType());
+ mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy);
+ if (!promotionTy.isNull()) {
+ cgf.cgm.errorNYI("ComplexExprEmitter::VisitUnaryMinus emitUnPromotedValue");
+ return {};
+ }
+ return result;
+}
+
mlir::Value ComplexExprEmitter::emitConstant(
const CIRGenFunction::ConstantEmission &constant, Expr *e) {
assert(constant && "not a constant");
@@ -534,13 +582,22 @@ mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
return emitBin##OP(emitBinOps(bo, promotionTy));
HANDLE_BINOP(Add)
HANDLE_BINOP(Sub)
+ HANDLE_BINOP(Mul)
#undef HANDLE_BINOP
default:
break;
}
- } else if (isa<UnaryOperator>(e)) {
- cgf.cgm.errorNYI("emitPromoted UnaryOperator");
- return {};
+ } else if (const auto *unaryOp = dyn_cast<UnaryOperator>(e)) {
+ switch (unaryOp->getOpcode()) {
+ case UO_Minus:
+ case UO_Plus: {
+ auto kind = unaryOp->getOpcode() == UO_Plus ? cir::UnaryOpKind::Plus
+ : cir::UnaryOpKind::Minus;
+ return VisitPlusMinus(unaryOp, kind, promotionTy);
+ }
+ default:
+ break;
+ }
}
mlir::Value result = Visit(const_cast<Expr *>(e));
@@ -585,6 +642,31 @@ mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) {
return builder.create<cir::ComplexSubOp>(op.loc, op.lhs, op.rhs);
}
+static cir::ComplexRangeKind
+getComplexRangeAttr(LangOptions::ComplexRangeKind range) {
+ switch (range) {
+ case LangOptions::CX_Full:
+ return cir::ComplexRangeKind::Full;
+ case LangOptions::CX_Improved:
+ return cir::ComplexRangeKind::Improved;
+ case LangOptions::CX_Promoted:
+ return cir::ComplexRangeKind::Promoted;
+ case LangOptions::CX_Basic:
+ return cir::ComplexRangeKind::Basic;
+ case LangOptions::CX_None:
+ // The default value for ComplexRangeKind is Full is no option is selected
+ return cir::ComplexRangeKind::Full;
+ }
+}
+
+mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) {
+ assert(!cir::MissingFeatures::fastMathFlags());
+ assert(!cir::MissingFeatures::cgFPOptionsRAII());
+ cir::ComplexRangeKind rangeKind =
+ getComplexRangeAttr(op.fpFeatures.getComplexRange());
+ return builder.create<cir::ComplexMulOp>(op.loc, op.lhs, op.rhs, rangeKind);
+}
+
LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) {
assert(e->getOpcode() == BO_Assign && "Expected assign op");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 2523b0f..32c1c1a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -48,8 +48,8 @@ struct BinOpInfo {
/// Check if the binop can result in integer overflow.
bool mayHaveIntegerOverflow() const {
// Without constant input, we can't rule out overflow.
- auto lhsci = dyn_cast<cir::ConstantOp>(lhs.getDefiningOp());
- auto rhsci = dyn_cast<cir::ConstantOp>(rhs.getDefiningOp());
+ auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
+ auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
if (!lhsci || !rhsci)
return true;
@@ -439,7 +439,7 @@ public:
value = builder.getTrue(cgf.getLoc(e->getExprLoc()));
} else if (type->isIntegerType()) {
QualType promotedType;
- bool canPerformLossyDemotionCheck = false;
+ [[maybe_unused]] bool canPerformLossyDemotionCheck = false;
if (cgf.getContext().isPromotableIntegerType(type)) {
promotedType = cgf.getContext().getPromotedIntegerType(type);
assert(promotedType != type && "Shouldn't promote to the same type.");
@@ -626,6 +626,7 @@ public:
mlir::Value VisitCXXThisExpr(CXXThisExpr *te) { return cgf.loadCXXThis(); }
+ mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
mlir::Value VisitCXXNewExpr(const CXXNewExpr *e) {
return cgf.emitCXXNewExpr(e);
}
@@ -1217,6 +1218,29 @@ mlir::Value ScalarExprEmitter::emitCompoundAssign(
return emitLoadOfLValue(lhs, e->getExprLoc());
}
+mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
+ mlir::Location scopeLoc = cgf.getLoc(e->getSourceRange());
+ mlir::OpBuilder &builder = cgf.builder;
+
+ auto scope = cir::ScopeOp::create(
+ builder, scopeLoc,
+ /*scopeBuilder=*/
+ [&](mlir::OpBuilder &b, mlir::Type &yieldTy, mlir::Location loc) {
+ CIRGenFunction::LexicalScope lexScope{cgf, loc,
+ builder.getInsertionBlock()};
+ mlir::Value scopeYieldVal = Visit(e->getSubExpr());
+ if (scopeYieldVal) {
+ // Defend against dominance problems caused by jumps out of expression
+ // evaluation through the shared cleanup block.
+ lexScope.forceCleanup();
+ cir::YieldOp::create(builder, loc, scopeYieldVal);
+ yieldTy = scopeYieldVal.getType();
+ }
+ });
+
+ return scope.getNumResults() > 0 ? scope->getResult(0) : nullptr;
+}
+
} // namespace
LValue
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index c65d025..f8e7347 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -216,11 +216,12 @@ void CIRGenFunction::emitAndUpdateRetAlloca(QualType type, mlir::Location loc,
void CIRGenFunction::declare(mlir::Value addrVal, const Decl *var, QualType ty,
mlir::Location loc, CharUnits alignment,
bool isParam) {
- const auto *namedVar = dyn_cast_or_null<NamedDecl>(var);
- assert(namedVar && "Needs a named decl");
+ assert(isa<NamedDecl>(var) && "Needs a named decl");
assert(!cir::MissingFeatures::cgfSymbolTable());
- auto allocaOp = cast<cir::AllocaOp>(addrVal.getDefiningOp());
+ auto allocaOp = addrVal.getDefiningOp<cir::AllocaOp>();
+ assert(allocaOp && "expected cir::AllocaOp");
+
if (isParam)
allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
if (ty->isReferenceType() || ty.isConstQualified())
@@ -801,6 +802,8 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
case Expr::CXXDynamicCastExprClass:
case Expr::ImplicitCastExprClass:
return emitCastLValue(cast<CastExpr>(e));
+ case Expr::MaterializeTemporaryExprClass:
+ return emitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(e));
}
}
@@ -811,6 +814,10 @@ static std::string getVersionedTmpName(llvm::StringRef name, unsigned cnt) {
return std::string(out.str());
}
+std::string CIRGenFunction::getCounterRefTmpAsString() {
+ return getVersionedTmpName("ref.tmp", counterRefTmp++);
+}
+
std::string CIRGenFunction::getCounterAggTmpAsString() {
return getVersionedTmpName("agg.tmp", counterAggTmp++);
}
@@ -943,6 +950,7 @@ void CIRGenFunction::emitVariablyModifiedType(QualType type) {
case Type::HLSLInlineSpirv:
case Type::PredefinedSugar:
cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType");
+ break;
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 603f750..68d54bb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -325,7 +325,9 @@ public:
};
/// Hold counters for incrementally naming temporaries
+ unsigned counterRefTmp = 0;
unsigned counterAggTmp = 0;
+ std::string getCounterRefTmpAsString();
std::string getCounterAggTmpAsString();
/// Helpers to convert Clang's SourceLocation to a MLIR Location.
@@ -604,6 +606,19 @@ public:
void popCleanupBlocks(size_t oldCleanupStackDepth);
void popCleanupBlock();
+ /// Push a cleanup to be run at the end of the current full-expression. Safe
+ /// against the possibility that we're currently inside a
+ /// conditionally-evaluated expression.
+ template <class T, class... As>
+ void pushFullExprCleanup(CleanupKind kind, As... a) {
+ // If we're not in a conditional branch, or if none of the
+ // arguments requires saving, then use the unconditional cleanup.
+ if (!isInConditionalBranch())
+ return ehStack.pushCleanup<T>(kind, a...);
+
+ cgm.errorNYI("pushFullExprCleanup in conditional branch");
+ }
+
/// Enters a new scope for capturing cleanups, all of which
/// will be executed once the scope is exited.
class RunCleanupsScope {
@@ -619,6 +634,7 @@ public:
protected:
CIRGenFunction &cgf;
+ public:
/// Enter a new cleanup scope.
explicit RunCleanupsScope(CIRGenFunction &cgf)
: performCleanup(true), cgf(cgf) {
@@ -801,6 +817,9 @@ public:
static Destroyer destroyCXXObject;
+ void pushDestroy(CleanupKind kind, Address addr, QualType type,
+ Destroyer *destroyer);
+
Destroyer *getDestroyer(clang::QualType::DestructionKind kind);
/// ----------------------
@@ -858,7 +877,8 @@ public:
Address emitArrayToPointerDecay(const Expr *array);
- AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d);
+ AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d,
+ mlir::OpBuilder::InsertPoint ip = {});
/// Emit code and set up symbol table for a variable declaration with auto,
/// register, or no storage class specifier. These turn into simple stack
@@ -870,6 +890,8 @@ public:
void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
clang::QualType::DestructionKind dtorKind);
+ void maybeEmitDeferredVarDeclInit(const VarDecl *vd);
+
void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl,
CXXCtorInitializer *baseInit);
@@ -1059,7 +1081,7 @@ public:
void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s);
- void emitDecl(const clang::Decl &d);
+ void emitDecl(const clang::Decl &d, bool evaluateConditionDecl = false);
mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);
LValue emitDeclRefLValue(const clang::DeclRefExpr *e);
@@ -1136,6 +1158,8 @@ public:
const clang::FieldDecl *field,
llvm::StringRef fieldName);
+ LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
+
LValue emitMemberExpr(const MemberExpr *e);
/// Given an expression with a pointer type, emit the value and compute our
@@ -1375,6 +1399,7 @@ public:
mlir::Location beginLoc;
mlir::Value varValue;
std::string name;
+ QualType baseType;
llvm::SmallVector<mlir::Value> bounds;
};
// Gets the collection of info required to lower and OpenACC clause or cache
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 623b84f..b143682 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -656,8 +656,6 @@ mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative) {
- const QualType astTy = vd->getType();
-
if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable");
return;
@@ -701,7 +699,7 @@ void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
// never attempt to emit a tentative definition if a real one
// exists. A use may still exists, however, so we still may need
// to do a RAUW.
- assert(!astTy->isIncompleteType() && "Unexpected incomplete type");
+ assert(!vd->getType()->isIncompleteType() && "Unexpected incomplete type");
init = builder.getZeroInitAttr(convertType(vd->getType()));
} else {
emitter.emplace(*this);
@@ -1308,8 +1306,13 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
break;
}
- case Decl::Var: {
+ case Decl::Var:
+ case Decl::Decomposition: {
auto *vd = cast<VarDecl>(decl);
+ if (isa<DecompositionDecl>(decl)) {
+ errorNYI(decl->getSourceRange(), "global variable decompositions");
+ break;
+ }
emitGlobal(vd);
break;
}
@@ -1331,8 +1334,14 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
break;
// No code generation needed.
- case Decl::UsingShadow:
+ case Decl::ClassTemplate:
+ case Decl::Concept:
+ case Decl::CXXDeductionGuide:
case Decl::Empty:
+ case Decl::FunctionTemplate:
+ case Decl::StaticAssert:
+ case Decl::TypeAliasTemplate:
+ case Decl::UsingShadow:
break;
case Decl::CXXConstructor:
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
index 49ff124..32095cb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
@@ -119,7 +119,7 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
if (const auto *memExpr = dyn_cast<MemberExpr>(curVarExpr))
return {exprLoc, emitMemberExpr(memExpr).getPointer(), exprString,
- std::move(bounds)};
+ curVarExpr->getType(), std::move(bounds)};
// Sema has made sure that only 4 types of things can get here, array
// subscript, array section, member expr, or DRE to a var decl (or the
@@ -127,5 +127,5 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
// right.
const auto *dre = cast<DeclRefExpr>(curVarExpr);
return {exprLoc, emitDeclRefLValue(dre).getPointer(), exprString,
- std::move(bounds)};
+ curVarExpr->getType(), std::move(bounds)};
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
index e45d3b8f..5a6e665 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
@@ -12,6 +12,7 @@
#include <type_traits>
+#include "CIRGenCXXABI.h"
#include "CIRGenFunction.h"
#include "clang/AST/ExprCXX.h"
@@ -355,6 +356,110 @@ class OpenACCClauseCIREmitter final
}
}
+ template <typename RecipeTy>
+ RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
+ DeclContext *dc, QualType baseType,
+ mlir::Value mainOp) {
+ mlir::ModuleOp mod =
+ builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
+
+ std::string recipeName;
+ {
+ llvm::raw_string_ostream stream(recipeName);
+ if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
+ stream << "privatization_";
+ } else if constexpr (std::is_same_v<RecipeTy,
+ mlir::acc::FirstprivateRecipeOp>) {
+ stream << "firstprivatization_";
+
+ } else if constexpr (std::is_same_v<RecipeTy,
+ mlir::acc::ReductionRecipeOp>) {
+ stream << "reduction_";
+ // We don't have the reduction operation here well enough to know how to
+ // spell this correctly (+ == 'add', etc), so when we implement
+ // 'reduction' we have to do that here.
+ cgf.cgm.errorNYI(varRef->getSourceRange(),
+ "OpeNACC reduction recipe creation");
+ } else {
+ static_assert(!sizeof(RecipeTy), "Unknown Recipe op kind");
+ }
+
+ MangleContext &mc = cgf.cgm.getCXXABI().getMangleContext();
+ mc.mangleCanonicalTypeName(baseType, stream);
+ }
+
+ if (auto recipe = mod.lookupSymbol<RecipeTy>(recipeName))
+ return recipe;
+
+ mlir::Location loc = cgf.cgm.getLoc(varRef->getBeginLoc());
+ mlir::Location locEnd = cgf.cgm.getLoc(varRef->getEndLoc());
+
+ mlir::OpBuilder modBuilder(mod.getBodyRegion());
+ auto recipe =
+ RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
+
+ // Magic-up a var-decl so we can use normal init/destruction operations for
+ // a variable declaration.
+ VarDecl &tempDecl = *VarDecl::Create(
+ astCtx, dc, varRef->getBeginLoc(), varRef->getBeginLoc(),
+ &astCtx.Idents.get("openacc.private.init"), baseType,
+ astCtx.getTrivialTypeSourceInfo(baseType), SC_Auto);
+ CIRGenFunction::AutoVarEmission tempDeclEmission{
+ CIRGenFunction::AutoVarEmission::invalid()};
+
+ // Init section.
+ {
+ llvm::SmallVector<mlir::Type> argsTys{mainOp.getType()};
+ llvm::SmallVector<mlir::Location> argsLocs{loc};
+ builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(),
+ argsTys, argsLocs);
+ builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
+
+ if constexpr (!std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
+ // We have only implemented 'init' for private, so make this NYI until
+ // we have explicitly implemented everything.
+ cgf.cgm.errorNYI(varRef->getSourceRange(),
+ "OpenACC non-private recipe init");
+ }
+
+ tempDeclEmission =
+ cgf.emitAutoVarAlloca(tempDecl, builder.saveInsertionPoint());
+ cgf.emitAutoVarInit(tempDeclEmission);
+
+ mlir::acc::YieldOp::create(builder, locEnd);
+ }
+
+ // Copy section.
+ if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp> ||
+ std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
+ // TODO: OpenACC: 'private' doesn't emit this, but for the other two we
+ // have to figure out what 'copy' means here.
+ cgf.cgm.errorNYI(varRef->getSourceRange(),
+ "OpenACC record type privatization copy section");
+ }
+
+ // Destroy section (doesn't currently exist).
+ if (tempDecl.needsDestruction(cgf.getContext())) {
+ llvm::SmallVector<mlir::Type> argsTys{mainOp.getType()};
+ llvm::SmallVector<mlir::Location> argsLocs{loc};
+ mlir::Block *block = builder.createBlock(&recipe.getDestroyRegion(),
+ recipe.getDestroyRegion().end(),
+ argsTys, argsLocs);
+ builder.setInsertionPointToEnd(&recipe.getDestroyRegion().back());
+
+ mlir::Type elementTy =
+ mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
+ Address addr{block->getArgument(0), elementTy,
+ cgf.getContext().getDeclAlign(&tempDecl)};
+ cgf.emitDestroy(addr, baseType,
+ cgf.getDestroyer(QualType::DK_cxx_destructor));
+
+ mlir::acc::YieldOp::create(builder, locEnd);
+ }
+
+ return recipe;
+ }
+
public:
OpenACCClauseCIREmitter(OpTy &operation, CIRGen::CIRGenFunction &cgf,
CIRGen::CIRGenBuilderTy &builder,
@@ -971,6 +1076,37 @@ public:
llvm_unreachable("Unknown construct kind in VisitAttachClause");
}
}
+
+ void VisitPrivateClause(const OpenACCPrivateClause &clause) {
+ if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp,
+ mlir::acc::LoopOp>) {
+ for (const Expr *var : clause.getVarList()) {
+ CIRGenFunction::OpenACCDataOperandInfo opInfo =
+ cgf.getOpenACCDataOperandInfo(var);
+ auto privateOp = mlir::acc::PrivateOp::create(
+ builder, opInfo.beginLoc, opInfo.varValue, /*structured=*/true,
+ /*implicit=*/false, opInfo.name, opInfo.bounds);
+ privateOp.setDataClause(mlir::acc::DataClause::acc_private);
+
+ {
+ mlir::OpBuilder::InsertionGuard guardCase(builder);
+ auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
+ cgf.getContext(), var, Decl::castToDeclContext(cgf.curFuncDecl),
+ opInfo.baseType, privateOp.getResult());
+ // TODO: OpenACC: The dialect is going to change in the near future to
+ // have these be on a different operation, so when that changes, we
+ // probably need to change these here.
+ operation.addPrivatization(builder.getContext(), privateOp, recipe);
+ }
+ }
+ } else if constexpr (isCombinedType<OpTy>) {
+ // Despite this being valid on ParallelOp or SerialOp, combined type
+ // applies to the 'loop'.
+ applyToLoopOp(clause);
+ } else {
+ llvm_unreachable("Unknown construct kind in VisitPrivateClause");
+ }
+ }
};
template <typename OpTy>
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
index e4ec380..ecf31a7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -41,7 +41,7 @@ struct CIRRecordLowering final {
// member type that ensures correct rounding.
struct MemberInfo final {
CharUnits offset;
- enum class InfoKind { Field, Base } kind;
+ enum class InfoKind { VFPtr, Field, Base } kind;
mlir::Type data;
union {
const FieldDecl *fieldDecl;
@@ -87,10 +87,15 @@ struct CIRRecordLowering final {
accumulateBitFields(RecordDecl::field_iterator field,
RecordDecl::field_iterator fieldEnd);
+ mlir::Type getVFPtrType();
+
bool isAAPCS() const {
return astContext.getTargetInfo().getABI().starts_with("aapcs");
}
+ /// Helper function to check if the target machine is BigEndian.
+ bool isBigEndian() const { return astContext.getTargetInfo().isBigEndian(); }
+
CharUnits bitsToCharUnits(uint64_t bitOffset) {
return astContext.toCharUnitsFromBits(bitOffset);
}
@@ -496,11 +501,7 @@ void CIRRecordLowering::accumulateFields() {
fieldEnd = recordDecl->field_end();
field != fieldEnd;) {
if (field->isBitField()) {
- RecordDecl::field_iterator start = field;
- // Iterate to gather the list of bitfields.
- for (++field; field != fieldEnd && field->isBitField(); ++field)
- ;
- field = accumulateBitFields(start, field);
+ field = accumulateBitFields(field, fieldEnd);
assert((field == fieldEnd || !field->isBitField()) &&
"Failed to accumulate all the bitfields");
} else if (!field->isZeroSize(astContext)) {
@@ -771,7 +772,104 @@ void CIRRecordLowering::computeVolatileBitfields() {
!cirGenTypes.getCGModule().getCodeGenOpts().AAPCSBitfieldWidth)
return;
- assert(!cir::MissingFeatures::armComputeVolatileBitfields());
+ for (auto &[field, info] : bitFields) {
+ mlir::Type resLTy = cirGenTypes.convertTypeForMem(field->getType());
+
+ if (astContext.toBits(astRecordLayout.getAlignment()) <
+ getSizeInBits(resLTy).getQuantity())
+ continue;
+
+ // CIRRecordLowering::setBitFieldInfo() pre-adjusts the bit-field offsets
+ // for big-endian targets, but it assumes a container of width
+ // info.storageSize. Since AAPCS uses a different container size (width
+ // of the type), we first undo that calculation here and redo it once
+ // the bit-field offset within the new container is calculated.
+ const unsigned oldOffset =
+ isBigEndian() ? info.storageSize - (info.offset + info.size)
+ : info.offset;
+ // Offset to the bit-field from the beginning of the struct.
+ const unsigned absoluteOffset =
+ astContext.toBits(info.storageOffset) + oldOffset;
+
+ // Container size is the width of the bit-field type.
+ const unsigned storageSize = getSizeInBits(resLTy).getQuantity();
+ // Nothing to do if the access uses the desired
+ // container width and is naturally aligned.
+ if (info.storageSize == storageSize && (oldOffset % storageSize == 0))
+ continue;
+
+ // Offset within the container.
+ unsigned offset = absoluteOffset & (storageSize - 1);
+ // Bail out if an aligned load of the container cannot cover the entire
+ // bit-field. This can happen for example, if the bit-field is part of a
+ // packed struct. AAPCS does not define access rules for such cases, we let
+ // clang to follow its own rules.
+ if (offset + info.size > storageSize)
+ continue;
+
+ // Re-adjust offsets for big-endian targets.
+ if (isBigEndian())
+ offset = storageSize - (offset + info.size);
+
+ const CharUnits storageOffset =
+ astContext.toCharUnitsFromBits(absoluteOffset & ~(storageSize - 1));
+ const CharUnits end = storageOffset +
+ astContext.toCharUnitsFromBits(storageSize) -
+ CharUnits::One();
+
+ const ASTRecordLayout &layout =
+ astContext.getASTRecordLayout(field->getParent());
+ // If we access outside memory outside the record, than bail out.
+ const CharUnits recordSize = layout.getSize();
+ if (end >= recordSize)
+ continue;
+
+ // Bail out if performing this load would access non-bit-fields members.
+ bool conflict = false;
+ for (const auto *f : recordDecl->fields()) {
+ // Allow sized bit-fields overlaps.
+ if (f->isBitField() && !f->isZeroLengthBitField())
+ continue;
+
+ const CharUnits fOffset = astContext.toCharUnitsFromBits(
+ layout.getFieldOffset(f->getFieldIndex()));
+
+ // As C11 defines, a zero sized bit-field defines a barrier, so
+ // fields after and before it should be race condition free.
+ // The AAPCS acknowledges it and imposes no restritions when the
+ // natural container overlaps a zero-length bit-field.
+ if (f->isZeroLengthBitField()) {
+ if (end > fOffset && storageOffset < fOffset) {
+ conflict = true;
+ break;
+ }
+ }
+
+ const CharUnits fEnd =
+ fOffset +
+ astContext.toCharUnitsFromBits(astContext.toBits(
+ getSizeInBits(cirGenTypes.convertTypeForMem(f->getType())))) -
+ CharUnits::One();
+ // If no overlap, continue.
+ if (end < fOffset || fEnd < storageOffset)
+ continue;
+
+ // The desired load overlaps a non-bit-field member, bail out.
+ conflict = true;
+ break;
+ }
+
+ if (conflict)
+ continue;
+ // Write the new bit-field access parameters.
+ // As the storage offset now is defined as the number of elements from the
+ // start of the structure, we should divide the Offset by the element size.
+ info.volatileStorageOffset =
+ storageOffset /
+ astContext.toCharUnitsFromBits(storageSize).getQuantity();
+ info.volatileStorageSize = storageSize;
+ info.volatileOffset = offset;
+ }
}
void CIRRecordLowering::accumulateBases(const CXXRecordDecl *cxxRecordDecl) {
@@ -802,9 +900,14 @@ void CIRRecordLowering::accumulateBases(const CXXRecordDecl *cxxRecordDecl) {
void CIRRecordLowering::accumulateVPtrs() {
if (astRecordLayout.hasOwnVFPtr())
- cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
- "accumulateVPtrs: hasOwnVFPtr");
+ members.push_back(MemberInfo(CharUnits::Zero(), MemberInfo::InfoKind::VFPtr,
+ getVFPtrType()));
+
if (astRecordLayout.hasOwnVBPtr())
cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
"accumulateVPtrs: hasOwnVBPtr");
}
+
+mlir::Type CIRRecordLowering::getVFPtrType() {
+ return cir::VPtrType::get(builder.getContext());
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
index 21bee33..50642e7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
@@ -79,14 +79,15 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
#define EXPR(Type, Base) case Stmt::Type##Class:
#include "clang/AST/StmtNodes.inc"
{
- // Remember the block we came in on.
- mlir::Block *incoming = builder.getInsertionBlock();
- assert(incoming && "expression emission must have an insertion point");
+ assert(builder.getInsertionBlock() &&
+ "expression emission must have an insertion point");
emitIgnoredExpr(cast<Expr>(s));
- mlir::Block *outgoing = builder.getInsertionBlock();
- assert(outgoing && "expression emission cleared block!");
+ // Classic codegen has a check here to see if the emitter created a new
+ // block that isn't used (comparing the incoming and outgoing insertion
+ // points) and deletes the outgoing block if it's not used. In CIR, we
+ // will handle that during the cir.canonicalize pass.
return mlir::success();
}
case Stmt::IfStmtClass:
@@ -363,8 +364,8 @@ mlir::LogicalResult CIRGenFunction::emitIfStmt(const IfStmt &s) {
mlir::LogicalResult CIRGenFunction::emitDeclStmt(const DeclStmt &s) {
assert(builder.getInsertionBlock() && "expected valid insertion point");
- for (const Decl *I : s.decls())
- emitDecl(*I);
+ for (const Decl *i : s.decls())
+ emitDecl(*i, /*evaluateConditionDecl=*/true);
return mlir::success();
}
@@ -875,7 +876,7 @@ mlir::LogicalResult CIRGenFunction::emitSwitchStmt(const clang::SwitchStmt &s) {
return mlir::failure();
if (s.getConditionVariable())
- emitDecl(*s.getConditionVariable());
+ emitDecl(*s.getConditionVariable(), /*evaluateConditionDecl=*/true);
mlir::Value condV = emitScalarExpr(s.getCond());
diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
index 99d6528..b0357d9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -152,9 +152,30 @@ void CIRGenerator::HandleTagDeclDefinition(TagDecl *d) {
cgm->errorNYI(d->getSourceRange(), "HandleTagDeclDefinition: OpenMP");
}
+void CIRGenerator::HandleTagDeclRequiredDefinition(const TagDecl *D) {
+ if (diags.hasErrorOccurred())
+ return;
+
+ assert(!cir::MissingFeatures::generateDebugInfo());
+}
+
+void CIRGenerator::HandleCXXStaticMemberVarInstantiation(VarDecl *D) {
+ if (diags.hasErrorOccurred())
+ return;
+
+ cgm->errorNYI(D->getSourceRange(), "HandleCXXStaticMemberVarInstantiation");
+}
+
void CIRGenerator::CompleteTentativeDefinition(VarDecl *d) {
if (diags.hasErrorOccurred())
return;
cgm->emitTentativeDefinition(d);
}
+
+void CIRGenerator::HandleVTable(CXXRecordDecl *rd) {
+ if (diags.hasErrorOccurred())
+ return;
+
+ cgm->errorNYI(rd->getSourceRange(), "HandleVTable");
+}
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 1c3a310..d3fcac1 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -606,7 +606,7 @@ static Value tryFoldCastChain(cir::CastOp op) {
if (!isIntOrBoolCast(op))
break;
head = op;
- op = dyn_cast_or_null<cir::CastOp>(head.getSrc().getDefiningOp());
+ op = head.getSrc().getDefiningOp<cir::CastOp>();
}
if (head == tail)
@@ -1802,7 +1802,7 @@ OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) {
}
if (isBoolNot(*this))
- if (auto previous = dyn_cast_or_null<UnaryOp>(getInput().getDefiningOp()))
+ if (auto previous = getInput().getDefiningOp<cir::UnaryOp>())
if (isBoolNot(previous))
return previous.getInput();
@@ -1833,7 +1833,7 @@ LogicalResult cir::GetMemberOp::verify() {
OpFoldResult cir::VecCreateOp::fold(FoldAdaptor adaptor) {
if (llvm::any_of(getElements(), [](mlir::Value value) {
- return !mlir::isa<cir::ConstantOp>(value.getDefiningOp());
+ return !value.getDefiningOp<cir::ConstantOp>();
}))
return {};
@@ -2184,8 +2184,7 @@ LogicalResult cir::ComplexRealOp::verify() {
}
OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
- if (auto complexCreateOp =
- dyn_cast_or_null<cir::ComplexCreateOp>(getOperand().getDefiningOp()))
+ if (auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
return complexCreateOp.getOperand(0);
auto complex =
@@ -2206,8 +2205,7 @@ LogicalResult cir::ComplexImagOp::verify() {
}
OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) {
- if (auto complexCreateOp =
- dyn_cast_or_null<cir::ComplexCreateOp>(getOperand().getDefiningOp()))
+ if (auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
return complexCreateOp.getOperand(1);
auto complex =
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 40da5e6..4fecb01 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -698,6 +698,23 @@ BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
}
//===----------------------------------------------------------------------===//
+// VPtrType Definitions
+//===----------------------------------------------------------------------===//
+
+llvm::TypeSize
+VPtrType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
+ mlir::DataLayoutEntryListRef params) const {
+ // FIXME: consider size differences under different ABIs
+ return llvm::TypeSize::getFixed(64);
+}
+
+uint64_t VPtrType::getABIAlignment(const mlir::DataLayout &dataLayout,
+ mlir::DataLayoutEntryListRef params) const {
+ // FIXME: consider alignment differences under different ABIs
+ return 8;
+}
+
+//===----------------------------------------------------------------------===//
// ArrayType Definitions
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp b/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp
index 3b7f08c4..3c6f768 100644
--- a/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp
@@ -97,8 +97,8 @@ private:
// Check whether the region/block contains a cir.const followed by a
// cir.yield that yields the value.
auto yieldOp = mlir::cast<cir::YieldOp>(onlyBlock.getTerminator());
- auto yieldValueDefOp = mlir::dyn_cast_if_present<cir::ConstantOp>(
- yieldOp.getArgs()[0].getDefiningOp());
+ auto yieldValueDefOp =
+ yieldOp.getArgs()[0].getDefiningOp<cir::ConstantOp>();
return yieldValueDefOp && yieldValueDefOp->getBlock() == &onlyBlock;
}
};
@@ -126,18 +126,13 @@ struct SimplifySelect : public OpRewritePattern<SelectOp> {
LogicalResult matchAndRewrite(SelectOp op,
PatternRewriter &rewriter) const final {
- mlir::Operation *trueValueOp = op.getTrueValue().getDefiningOp();
- mlir::Operation *falseValueOp = op.getFalseValue().getDefiningOp();
- auto trueValueConstOp =
- mlir::dyn_cast_if_present<cir::ConstantOp>(trueValueOp);
- auto falseValueConstOp =
- mlir::dyn_cast_if_present<cir::ConstantOp>(falseValueOp);
- if (!trueValueConstOp || !falseValueConstOp)
+ auto trueValueOp = op.getTrueValue().getDefiningOp<cir::ConstantOp>();
+ auto falseValueOp = op.getFalseValue().getDefiningOp<cir::ConstantOp>();
+ if (!trueValueOp || !falseValueOp)
return mlir::failure();
- auto trueValue = mlir::dyn_cast<cir::BoolAttr>(trueValueConstOp.getValue());
- auto falseValue =
- mlir::dyn_cast<cir::BoolAttr>(falseValueConstOp.getValue());
+ auto trueValue = trueValueOp.getValueAttr<cir::BoolAttr>();
+ auto falseValue = falseValueOp.getValueAttr<cir::BoolAttr>();
if (!trueValue || !falseValue)
return mlir::failure();
@@ -265,8 +260,7 @@ struct SimplifyVecSplat : public OpRewritePattern<VecSplatOp> {
LogicalResult matchAndRewrite(VecSplatOp op,
PatternRewriter &rewriter) const override {
mlir::Value splatValue = op.getValue();
- auto constant =
- mlir::dyn_cast_if_present<cir::ConstantOp>(splatValue.getDefiningOp());
+ auto constant = splatValue.getDefiningOp<cir::ConstantOp>();
if (!constant)
return mlir::failure();
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index ce3b30d..66260eb 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -15,7 +15,6 @@
#include "clang/CIR/Dialect/Passes.h"
#include "clang/CIR/MissingFeatures.h"
-#include <iostream>
#include <memory>
using namespace mlir;
@@ -28,21 +27,47 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> {
void runOnOp(mlir::Operation *op);
void lowerCastOp(cir::CastOp op);
+ void lowerComplexMulOp(cir::ComplexMulOp op);
void lowerUnaryOp(cir::UnaryOp op);
void lowerArrayDtor(cir::ArrayDtor op);
void lowerArrayCtor(cir::ArrayCtor op);
+ cir::FuncOp buildRuntimeFunction(
+ mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
+ cir::FuncType type,
+ cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage);
+
///
/// AST related
/// -----------
clang::ASTContext *astCtx;
+ /// Tracks current module.
+ mlir::ModuleOp mlirModule;
+
void setASTContext(clang::ASTContext *c) { astCtx = c; }
};
} // namespace
+cir::FuncOp LoweringPreparePass::buildRuntimeFunction(
+ mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
+ cir::FuncType type, cir::GlobalLinkageKind linkage) {
+ cir::FuncOp f = dyn_cast_or_null<FuncOp>(SymbolTable::lookupNearestSymbolFrom(
+ mlirModule, StringAttr::get(mlirModule->getContext(), name)));
+ if (!f) {
+ f = builder.create<cir::FuncOp>(loc, name, type);
+ f.setLinkageAttr(
+ cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage));
+ mlir::SymbolTable::setSymbolVisibility(
+ f, mlir::SymbolTable::Visibility::Private);
+
+ assert(!cir::MissingFeatures::opFuncExtraAttrs());
+ }
+ return f;
+}
+
static mlir::Value lowerScalarToComplexCast(mlir::MLIRContext &ctx,
cir::CastOp op) {
cir::CIRBaseBuilderTy builder(ctx);
@@ -128,6 +153,124 @@ void LoweringPreparePass::lowerCastOp(cir::CastOp op) {
}
}
+static mlir::Value buildComplexBinOpLibCall(
+ LoweringPreparePass &pass, CIRBaseBuilderTy &builder,
+ llvm::StringRef (*libFuncNameGetter)(llvm::APFloat::Semantics),
+ mlir::Location loc, cir::ComplexType ty, mlir::Value lhsReal,
+ mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag) {
+ cir::FPTypeInterface elementTy =
+ mlir::cast<cir::FPTypeInterface>(ty.getElementType());
+
+ llvm::StringRef libFuncName = libFuncNameGetter(
+ llvm::APFloat::SemanticsToEnum(elementTy.getFloatSemantics()));
+ llvm::SmallVector<mlir::Type, 4> libFuncInputTypes(4, elementTy);
+
+ cir::FuncType libFuncTy = cir::FuncType::get(libFuncInputTypes, ty);
+
+ // Insert a declaration for the runtime function to be used in Complex
+ // multiplication and division when needed
+ cir::FuncOp libFunc;
+ {
+ mlir::OpBuilder::InsertionGuard ipGuard{builder};
+ builder.setInsertionPointToStart(pass.mlirModule.getBody());
+ libFunc = pass.buildRuntimeFunction(builder, libFuncName, loc, libFuncTy);
+ }
+
+ cir::CallOp call =
+ builder.createCallOp(loc, libFunc, {lhsReal, lhsImag, rhsReal, rhsImag});
+ return call.getResult();
+}
+
+static llvm::StringRef
+getComplexMulLibCallName(llvm::APFloat::Semantics semantics) {
+ switch (semantics) {
+ case llvm::APFloat::S_IEEEhalf:
+ return "__mulhc3";
+ case llvm::APFloat::S_IEEEsingle:
+ return "__mulsc3";
+ case llvm::APFloat::S_IEEEdouble:
+ return "__muldc3";
+ case llvm::APFloat::S_PPCDoubleDouble:
+ return "__multc3";
+ case llvm::APFloat::S_x87DoubleExtended:
+ return "__mulxc3";
+ case llvm::APFloat::S_IEEEquad:
+ return "__multc3";
+ default:
+ llvm_unreachable("unsupported floating point type");
+ }
+}
+
+static mlir::Value lowerComplexMul(LoweringPreparePass &pass,
+ CIRBaseBuilderTy &builder,
+ mlir::Location loc, cir::ComplexMulOp op,
+ mlir::Value lhsReal, mlir::Value lhsImag,
+ mlir::Value rhsReal, mlir::Value rhsImag) {
+ // (a+bi) * (c+di) = (ac-bd) + (ad+bc)i
+ mlir::Value resultRealLhs =
+ builder.createBinop(loc, lhsReal, cir::BinOpKind::Mul, rhsReal);
+ mlir::Value resultRealRhs =
+ builder.createBinop(loc, lhsImag, cir::BinOpKind::Mul, rhsImag);
+ mlir::Value resultImagLhs =
+ builder.createBinop(loc, lhsReal, cir::BinOpKind::Mul, rhsImag);
+ mlir::Value resultImagRhs =
+ builder.createBinop(loc, lhsImag, cir::BinOpKind::Mul, rhsReal);
+ mlir::Value resultReal = builder.createBinop(
+ loc, resultRealLhs, cir::BinOpKind::Sub, resultRealRhs);
+ mlir::Value resultImag = builder.createBinop(
+ loc, resultImagLhs, cir::BinOpKind::Add, resultImagRhs);
+ mlir::Value algebraicResult =
+ builder.createComplexCreate(loc, resultReal, resultImag);
+
+ cir::ComplexType complexTy = op.getType();
+ cir::ComplexRangeKind rangeKind = op.getRange();
+ if (mlir::isa<cir::IntType>(complexTy.getElementType()) ||
+ rangeKind == cir::ComplexRangeKind::Basic ||
+ rangeKind == cir::ComplexRangeKind::Improved ||
+ rangeKind == cir::ComplexRangeKind::Promoted)
+ return algebraicResult;
+
+ assert(!cir::MissingFeatures::fastMathFlags());
+
+ // Check whether the real part and the imaginary part of the result are both
+ // NaN. If so, emit a library call to compute the multiplication instead.
+ // We check a value against NaN by comparing the value against itself.
+ mlir::Value resultRealIsNaN = builder.createIsNaN(loc, resultReal);
+ mlir::Value resultImagIsNaN = builder.createIsNaN(loc, resultImag);
+ mlir::Value resultRealAndImagAreNaN =
+ builder.createLogicalAnd(loc, resultRealIsNaN, resultImagIsNaN);
+
+ return builder
+ .create<cir::TernaryOp>(
+ loc, resultRealAndImagAreNaN,
+ [&](mlir::OpBuilder &, mlir::Location) {
+ mlir::Value libCallResult = buildComplexBinOpLibCall(
+ pass, builder, &getComplexMulLibCallName, loc, complexTy,
+ lhsReal, lhsImag, rhsReal, rhsImag);
+ builder.createYield(loc, libCallResult);
+ },
+ [&](mlir::OpBuilder &, mlir::Location) {
+ builder.createYield(loc, algebraicResult);
+ })
+ .getResult();
+}
+
+void LoweringPreparePass::lowerComplexMulOp(cir::ComplexMulOp op) {
+ cir::CIRBaseBuilderTy builder(getContext());
+ builder.setInsertionPointAfter(op);
+ mlir::Location loc = op.getLoc();
+ mlir::TypedValue<cir::ComplexType> lhs = op.getLhs();
+ mlir::TypedValue<cir::ComplexType> rhs = op.getRhs();
+ mlir::Value lhsReal = builder.createComplexReal(loc, lhs);
+ mlir::Value lhsImag = builder.createComplexImag(loc, lhs);
+ mlir::Value rhsReal = builder.createComplexReal(loc, rhs);
+ mlir::Value rhsImag = builder.createComplexImag(loc, rhs);
+ mlir::Value loweredResult = lowerComplexMul(*this, builder, loc, op, lhsReal,
+ lhsImag, rhsReal, rhsImag);
+ op.replaceAllUsesWith(loweredResult);
+ op.erase();
+}
+
void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) {
mlir::Type ty = op.getType();
if (!mlir::isa<cir::ComplexType>(ty))
@@ -155,7 +298,8 @@ void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) {
case cir::UnaryOpKind::Plus:
case cir::UnaryOpKind::Minus:
- llvm_unreachable("Complex unary Plus/Minus NYI");
+ resultReal = builder.createUnaryOp(loc, opKind, operandReal);
+ resultImag = builder.createUnaryOp(loc, opKind, operandImag);
break;
case cir::UnaryOpKind::Not:
@@ -268,18 +412,22 @@ void LoweringPreparePass::runOnOp(mlir::Operation *op) {
lowerArrayDtor(arrayDtor);
else if (auto cast = mlir::dyn_cast<cir::CastOp>(op))
lowerCastOp(cast);
+ else if (auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op))
+ lowerComplexMulOp(complexMul);
else if (auto unary = mlir::dyn_cast<cir::UnaryOp>(op))
lowerUnaryOp(unary);
}
void LoweringPreparePass::runOnOperation() {
mlir::Operation *op = getOperation();
+ if (isa<::mlir::ModuleOp>(op))
+ mlirModule = cast<::mlir::ModuleOp>(op);
llvm::SmallVector<mlir::Operation *> opsToTransform;
op->walk([&](mlir::Operation *op) {
- if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp, cir::UnaryOp>(
- op))
+ if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp,
+ cir::ComplexMulOp, cir::UnaryOp>(op))
opsToTransform.push_back(op);
});
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index 9264aa6..67bb565 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -84,6 +84,10 @@ public:
return true;
}
+ void HandleCXXStaticMemberVarInstantiation(clang::VarDecl *VD) override {
+ Gen->HandleCXXStaticMemberVarInstantiation(VD);
+ }
+
void HandleInlineFunctionDefinition(FunctionDecl *D) override {
Gen->HandleInlineFunctionDefinition(D);
}
@@ -147,9 +151,15 @@ public:
Gen->HandleTagDeclDefinition(D);
}
+ void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
+ Gen->HandleTagDeclRequiredDefinition(D);
+ }
+
void CompleteTentativeDefinition(VarDecl *D) override {
Gen->CompleteTentativeDefinition(D);
}
+
+ void HandleVTable(CXXRecordDecl *RD) override { Gen->HandleVTable(RD); }
};
} // namespace cir
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 957a51a..dc6e1b7 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -821,8 +821,7 @@ mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
// before it. To achieve that, look at unary minus, which already got
// lowered to "sub 0, x".
const auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp);
- auto unary = dyn_cast_if_present<cir::UnaryOp>(
- ptrStrideOp.getStride().getDefiningOp());
+ auto unary = ptrStrideOp.getStride().getDefiningOp<cir::UnaryOp>();
bool rewriteSub =
unary && unary.getKind() == cir::UnaryOpKind::Minus && sub;
if (rewriteSub)
@@ -1935,12 +1934,11 @@ mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
cir::SelectOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr {
- auto definingOp =
- mlir::dyn_cast_if_present<cir::ConstantOp>(value.getDefiningOp());
+ auto definingOp = value.getDefiningOp<cir::ConstantOp>();
if (!definingOp)
return {};
- auto constValue = mlir::dyn_cast<cir::BoolAttr>(definingOp.getValue());
+ auto constValue = definingOp.getValueAttr<cir::BoolAttr>();
if (!constValue)
return {};
@@ -2379,15 +2377,14 @@ mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
mlir::Value poison = rewriter.create<mlir::LLVM::PoisonOp>(loc, llvmTy);
mlir::Value elementValue = adaptor.getValue();
- if (mlir::isa<mlir::LLVM::PoisonOp>(elementValue.getDefiningOp())) {
+ if (elementValue.getDefiningOp<mlir::LLVM::PoisonOp>()) {
// If the splat value is poison, then we can just use poison value
// for the entire vector.
rewriter.replaceOp(op, poison);
return mlir::success();
}
- if (auto constValue =
- dyn_cast<mlir::LLVM::ConstantOp>(elementValue.getDefiningOp())) {
+ if (auto constValue = elementValue.getDefiningOp<mlir::LLVM::ConstantOp>()) {
if (auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 3f784fc..a648bde 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -973,6 +973,9 @@ public:
AddrOfSeen = false;
return Visit(E->getSubExpr());
}
+ const Expr *VisitBinaryOperator(const clang::BinaryOperator *Op) {
+ return Op->isCommaOp() ? Visit(Op->getRHS()) : nullptr;
+ }
};
} // end anonymous namespace
@@ -1148,7 +1151,8 @@ llvm::Value *CodeGenFunction::emitCountedByPointerSize(
assert(E->getCastKind() == CK_LValueToRValue &&
"must be an LValue to RValue cast");
- const MemberExpr *ME = dyn_cast<MemberExpr>(E->getSubExpr());
+ const MemberExpr *ME =
+ dyn_cast<MemberExpr>(E->getSubExpr()->IgnoreParenNoopCasts(getContext()));
if (!ME)
return nullptr;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 77fc3a2..1ce834d 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -643,16 +643,7 @@ unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc, bool Force) {
}
StringRef CGDebugInfo::getCurrentDirname() {
- if (!CGM.getCodeGenOpts().DebugCompilationDir.empty())
- return CGM.getCodeGenOpts().DebugCompilationDir;
-
- if (!CWDName.empty())
- return CWDName;
- llvm::ErrorOr<std::string> CWD =
- CGM.getFileSystem()->getCurrentWorkingDirectory();
- if (!CWD)
- return StringRef();
- return CWDName = internString(*CWD);
+ return CGM.getCodeGenOpts().DebugCompilationDir;
}
void CGDebugInfo::CreateCompileUnit() {
@@ -2641,6 +2632,8 @@ void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable,
const CXXRecordDecl *RD) {
if (!CGM.getTarget().getCXXABI().isItaniumFamily())
return;
+ if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly)
+ return;
ASTContext &Context = CGM.getContext();
StringRef SymbolName = "_vtable$";
@@ -3246,6 +3239,9 @@ llvm::DIModule *CGDebugInfo::getOrCreateModuleRef(ASTSourceDescriptor Mod,
std::string Remapped = remapDIPath(Path);
StringRef Relative(Remapped);
StringRef CompDir = TheCU->getDirectory();
+ if (CompDir.empty())
+ return Remapped;
+
if (Relative.consume_front(CompDir))
Relative.consume_front(llvm::sys::path::get_separator());
@@ -4805,7 +4801,7 @@ void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
const FunctionDecl *CalleeDecl) {
if (!CallOrInvoke)
return;
- auto *Func = CallOrInvoke->getCalledFunction();
+ auto *Func = dyn_cast<llvm::Function>(CallOrInvoke->getCalledOperand());
if (!Func)
return;
if (Func->getSubprogram())
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 411b2e7..497d3a6 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -158,7 +158,6 @@ class CGDebugInfo {
/// This is a storage for names that are constructed on demand. For
/// example, C++ destructors, C++ operators etc..
llvm::BumpPtrAllocator DebugInfoNames;
- StringRef CWDName;
llvm::DenseMap<const char *, llvm::TrackingMDRef> DIFileCache;
llvm::DenseMap<const FunctionDecl *, llvm::TrackingMDRef> SPCache;
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 90aed79..5a3d4e4 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -93,6 +93,7 @@ static llvm::StringRef GetUBSanTrapForHandler(SanitizerHandler ID) {
LIST_SANITIZER_CHECKS
#undef SANITIZER_CHECK
}
+ llvm_unreachable("unhandled switch case");
}
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
index e25b694..04c9192 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
@@ -2278,8 +2278,12 @@ void CGOpenMPRuntimeGPU::processRequiresDirective(const OMPRequiresDecl *D) {
case OffloadArch::SM_100a:
case OffloadArch::SM_101:
case OffloadArch::SM_101a:
+ case OffloadArch::SM_103:
+ case OffloadArch::SM_103a:
case OffloadArch::SM_120:
case OffloadArch::SM_120a:
+ case OffloadArch::SM_121:
+ case OffloadArch::SM_121a:
case OffloadArch::GFX600:
case OffloadArch::GFX601:
case OffloadArch::GFX602:
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 2c0767f..dc54c97 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -978,7 +978,7 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
CI.getPreprocessor());
std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
- CI, BA, &CI.getVirtualFileSystem(), *VMContext, std::move(LinkModules),
+ CI, BA, CI.getVirtualFileSystemPtr(), *VMContext, std::move(LinkModules),
InFile, std::move(OS), CoverageInfo));
BEConsumer = Result.get();
@@ -1156,7 +1156,7 @@ void CodeGenAction::ExecuteAction() {
// Set clang diagnostic handler. To do this we need to create a fake
// BackendConsumer.
- BackendConsumer Result(CI, BA, &CI.getVirtualFileSystem(), *VMContext,
+ BackendConsumer Result(CI, BA, CI.getVirtualFileSystemPtr(), *VMContext,
std::move(LinkModules), "", nullptr, nullptr,
TheModule.get());
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 4aafac3..38aaceb 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -2449,12 +2449,7 @@ CoverageMappingModuleGen::CoverageMappingModuleGen(
: CGM(CGM), SourceInfo(SourceInfo) {}
std::string CoverageMappingModuleGen::getCurrentDirname() {
- if (!CGM.getCodeGenOpts().CoverageCompilationDir.empty())
- return CGM.getCodeGenOpts().CoverageCompilationDir;
-
- SmallString<256> CWD;
- llvm::sys::fs::current_path(CWD);
- return CWD.str().str();
+ return CGM.getCodeGenOpts().CoverageCompilationDir;
}
std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) {
diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
index 95971e5..074f2a5 100644
--- a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
+++ b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
@@ -146,7 +146,7 @@ public:
: CI(CI), Diags(CI.getDiagnostics()), MainFileName(MainFileName),
OutputFileName(OutputFileName), Ctx(nullptr),
MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()),
- FS(&CI.getVirtualFileSystem()),
+ FS(CI.getVirtualFileSystemPtr()),
HeaderSearchOpts(CI.getHeaderSearchOpts()),
PreprocessorOpts(CI.getPreprocessorOpts()),
TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()),
diff --git a/clang/lib/CrossTU/CrossTranslationUnit.cpp b/clang/lib/CrossTU/CrossTranslationUnit.cpp
index 6d0f042..fb2a79a 100644
--- a/clang/lib/CrossTU/CrossTranslationUnit.cpp
+++ b/clang/lib/CrossTU/CrossTranslationUnit.cpp
@@ -563,9 +563,8 @@ CrossTranslationUnitContext::ASTLoader::loadFromDump(StringRef ASTDumpPath) {
auto DiagOpts = std::make_shared<DiagnosticOptions>();
TextDiagnosticPrinter *DiagClient =
new TextDiagnosticPrinter(llvm::errs(), *DiagOpts);
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, *DiagOpts, DiagClient));
+ auto Diags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(
+ DiagnosticIDs::create(), *DiagOpts, DiagClient);
return ASTUnit::LoadFromASTFile(
ASTDumpPath, CI.getPCHContainerOperations()->getRawReader(),
ASTUnit::LoadEverything, DiagOpts, Diags, CI.getFileSystemOpts(),
@@ -607,8 +606,8 @@ CrossTranslationUnitContext::ASTLoader::loadFromSource(
auto *DiagClient = new ForwardingDiagnosticConsumer{CI.getDiagnosticClient()};
IntrusiveRefCntPtr<DiagnosticIDs> DiagID{
CI.getDiagnostics().getDiagnosticIDs()};
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine{DiagID, *DiagOpts, DiagClient});
+ auto Diags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(DiagID, *DiagOpts,
+ DiagClient);
return ASTUnit::LoadFromCommandLine(
CommandLineArgs.begin(), (CommandLineArgs.end()),
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 99de951..586f287 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -3606,7 +3606,7 @@ class OffloadingActionBuilder final {
if (!CompileDeviceOnly) {
C.getDriver().Diag(diag::err_opt_not_valid_without_opt)
<< "-fhip-emit-relocatable"
- << "--cuda-device-only";
+ << "--offload-device-only";
}
}
}
@@ -4774,6 +4774,21 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
C.isOffloadingHostKind(Action::OFK_HIP) &&
!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false);
+ bool HIPRelocatableObj =
+ C.isOffloadingHostKind(Action::OFK_HIP) &&
+ Args.hasFlag(options::OPT_fhip_emit_relocatable,
+ options::OPT_fno_hip_emit_relocatable, false);
+
+ if (!HIPNoRDC && HIPRelocatableObj)
+ C.getDriver().Diag(diag::err_opt_not_valid_with_opt)
+ << "-fhip-emit-relocatable"
+ << "-fgpu-rdc";
+
+ if (!offloadDeviceOnly() && HIPRelocatableObj)
+ C.getDriver().Diag(diag::err_opt_not_valid_without_opt)
+ << "-fhip-emit-relocatable"
+ << "--offload-device-only";
+
// For HIP non-rdc non-device-only compilation, create a linker wrapper
// action for each host object to link, bundle and wrap device files in
// it.
@@ -4894,7 +4909,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
A->getOffloadingToolChain()->getTriple().isSPIRV();
if ((A->getType() != types::TY_Object && !IsAMDGCNSPIRV &&
A->getType() != types::TY_LTO_BC) ||
- !HIPNoRDC || !offloadDeviceOnly())
+ HIPRelocatableObj || !HIPNoRDC || !offloadDeviceOnly())
continue;
ActionList LinkerInput = {A};
A = C.MakeAction<LinkJobAction>(LinkerInput, types::TY_Image);
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index 207150e..25a16fe 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -671,7 +671,8 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
CmdArgs.push_back("--start-group");
AddRunTimeLibs(TC, D, CmdArgs, Args);
- CmdArgs.push_back("-lc");
+ if (!Args.hasArg(options::OPT_nolibc))
+ CmdArgs.push_back("-lc");
if (TC.hasValidGCCInstallation() || detectGCCToolchainAdjacent(D))
CmdArgs.push_back("-lgloss");
CmdArgs.push_back("--end-group");
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index f4674a5..4e1b1d9 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -226,17 +226,19 @@ static bool ShouldEnableAutolink(const ArgList &Args, const ToolChain &TC,
static const char *addDebugCompDirArg(const ArgList &Args,
ArgStringList &CmdArgs,
const llvm::vfs::FileSystem &VFS) {
+ std::string DebugCompDir;
if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
- options::OPT_fdebug_compilation_dir_EQ)) {
- if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ))
- CmdArgs.push_back(Args.MakeArgString(Twine("-fdebug-compilation-dir=") +
- A->getValue()));
+ options::OPT_fdebug_compilation_dir_EQ))
+ DebugCompDir = A->getValue();
+
+ if (DebugCompDir.empty()) {
+ if (llvm::ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory())
+ DebugCompDir = std::move(*CWD);
else
- A->render(Args, CmdArgs);
- } else if (llvm::ErrorOr<std::string> CWD =
- VFS.getCurrentWorkingDirectory()) {
- CmdArgs.push_back(Args.MakeArgString("-fdebug-compilation-dir=" + *CWD));
+ return nullptr;
}
+ CmdArgs.push_back(
+ Args.MakeArgString("-fdebug-compilation-dir=" + DebugCompDir));
StringRef Path(CmdArgs.back());
return Path.substr(Path.find('=') + 1).data();
}
@@ -525,17 +527,17 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
CmdArgs.push_back("-fcoverage-mcdc");
}
+ StringRef CoverageCompDir;
if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
- options::OPT_fcoverage_compilation_dir_EQ)) {
- if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ))
- CmdArgs.push_back(Args.MakeArgString(
- Twine("-fcoverage-compilation-dir=") + A->getValue()));
- else
- A->render(Args, CmdArgs);
- } else if (llvm::ErrorOr<std::string> CWD =
- D.getVFS().getCurrentWorkingDirectory()) {
- CmdArgs.push_back(Args.MakeArgString("-fcoverage-compilation-dir=" + *CWD));
- }
+ options::OPT_fcoverage_compilation_dir_EQ))
+ CoverageCompDir = A->getValue();
+ if (CoverageCompDir.empty()) {
+ if (auto CWD = D.getVFS().getCurrentWorkingDirectory())
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-fcoverage-compilation-dir=") + *CWD));
+ } else
+ CmdArgs.push_back(Args.MakeArgString(Twine("-fcoverage-compilation-dir=") +
+ CoverageCompDir));
if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) {
auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ);
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 256c266..334fcbb 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -295,17 +295,22 @@ static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
Format = A->getValue();
SmallString<128> F;
- const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
- if (A)
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_foptimization_record_file_EQ)) {
+ F = A->getValue();
+ F += ".";
+ } else if (const Arg *A = Args.getLastArg(options::OPT_dumpdir)) {
F = A->getValue();
- else if (Output.isFilename())
+ } else if (Output.isFilename()) {
F = Output.getFilename();
+ F += ".";
+ }
assert(!F.empty() && "Cannot determine remarks output name.");
// Append "opt.ld.<format>" to the end of the file name.
CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
- "opt-remarks-filename=" + F +
- ".opt.ld." + Format));
+ "opt-remarks-filename=" + F + "opt.ld." +
+ Format));
if (const Arg *A =
Args.getLastArg(options::OPT_foptimization_record_passes_EQ))
@@ -1075,9 +1080,17 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
}
}
- if (Args.hasArg(options::OPT_gsplit_dwarf))
- CmdArgs.push_back(Args.MakeArgString(
- Twine(PluginOptPrefix) + "dwo_dir=" + Output.getFilename() + "_dwo"));
+ if (Args.hasArg(options::OPT_gsplit_dwarf)) {
+ SmallString<128> F;
+ if (const Arg *A = Args.getLastArg(options::OPT_dumpdir)) {
+ F = A->getValue();
+ } else {
+ F = Output.getFilename();
+ F += "_";
+ }
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "dwo_dir=" + F + "dwo"));
+ }
if (IsThinLTO && !IsOSAIX)
CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + "thinlto"));
@@ -3001,12 +3014,12 @@ void tools::addOffloadCompressArgs(const llvm::opt::ArgList &TCArgs,
llvm::opt::ArgStringList &CmdArgs) {
if (TCArgs.hasFlag(options::OPT_offload_compress,
options::OPT_no_offload_compress, false))
- CmdArgs.push_back("-compress");
+ CmdArgs.push_back("--compress");
if (TCArgs.hasArg(options::OPT_v))
- CmdArgs.push_back("-verbose");
+ CmdArgs.push_back("--verbose");
if (auto *Arg = TCArgs.getLastArg(options::OPT_offload_compression_level_EQ))
CmdArgs.push_back(
- TCArgs.MakeArgString(Twine("-compression-level=") + Arg->getValue()));
+ TCArgs.MakeArgString(Twine("--compression-level=") + Arg->getValue()));
}
void tools::addMCModel(const Driver &D, const llvm::opt::ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 7d803be..fdfcea8 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -88,6 +88,8 @@ CudaVersion getCudaVersion(uint32_t raw_version) {
return CudaVersion::CUDA_126;
if (raw_version < 12090)
return CudaVersion::CUDA_128;
+ if (raw_version < 13000)
+ return CudaVersion::CUDA_129;
return CudaVersion::NEW;
}
@@ -547,22 +549,16 @@ void NVPTX::FatBinary::ConstructJob(Compilation &C, const JobAction &JA,
auto *A = II.getAction();
assert(A->getInputs().size() == 1 &&
"Device offload action is expected to have a single input");
- const char *gpu_arch_str = A->getOffloadingArch();
- assert(gpu_arch_str &&
+ StringRef GpuArch = A->getOffloadingArch();
+ assert(!GpuArch.empty() &&
"Device action expected to have associated a GPU architecture!");
- OffloadArch gpu_arch = StringToOffloadArch(gpu_arch_str);
- if (II.getType() == types::TY_PP_Asm &&
- !shouldIncludePTX(Args, gpu_arch_str))
+ if (II.getType() == types::TY_PP_Asm && !shouldIncludePTX(Args, GpuArch))
continue;
- // We need to pass an Arch of the form "sm_XX" for cubin files and
- // "compute_XX" for ptx.
- const char *Arch = (II.getType() == types::TY_PP_Asm)
- ? OffloadArchToVirtualArchString(gpu_arch)
- : gpu_arch_str;
- CmdArgs.push_back(
- Args.MakeArgString(llvm::Twine("--image=profile=") + Arch +
- ",file=" + getToolChain().getInputFilename(II)));
+ StringRef Kind = (II.getType() == types::TY_PP_Asm) ? "ptx" : "elf";
+ CmdArgs.push_back(Args.MakeArgString(
+ "--image3=kind=" + Kind + ",sm=" + GpuArch.drop_front(3) +
+ ",file=" + getToolChain().getInputFilename(II)));
}
for (const auto &A : Args.getAllArgValues(options::OPT_Xcuda_fatbinary))
@@ -683,6 +679,7 @@ void NVPTX::getNVPTXTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case CudaVersion::CUDA_##CUDA_VER: \
PtxFeature = "+ptx" #PTX_VER; \
break;
+ CASE_CUDA_VERSION(129, 88);
CASE_CUDA_VERSION(128, 87);
CASE_CUDA_VERSION(126, 85);
CASE_CUDA_VERSION(125, 85);
diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
index 80487fa..b51991bf 100644
--- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
+++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
@@ -45,15 +45,18 @@ std::pair<tooling::Replacements, unsigned>
IntegerLiteralSeparatorFixer::process(const Environment &Env,
const FormatStyle &Style) {
switch (Style.Language) {
- case FormatStyle::LK_Cpp:
- case FormatStyle::LK_ObjC:
- Separator = '\'';
- break;
case FormatStyle::LK_CSharp:
case FormatStyle::LK_Java:
case FormatStyle::LK_JavaScript:
Separator = '_';
break;
+ case FormatStyle::LK_Cpp:
+ case FormatStyle::LK_ObjC:
+ if (Style.Standard >= FormatStyle::LS_Cpp14) {
+ Separator = '\'';
+ break;
+ }
+ [[fallthrough]];
default:
return {};
}
@@ -114,7 +117,7 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
}
if (Style.isCpp()) {
// Hex alpha digits a-f/A-F must be at the end of the string literal.
- StringRef Suffixes = "_himnsuyd";
+ static constexpr StringRef Suffixes("_himnsuyd");
if (const auto Pos =
Text.find_first_of(IsBase16 ? Suffixes.drop_back() : Suffixes);
Pos != StringRef::npos) {
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index d28d2fd..4801d27 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1939,7 +1939,7 @@ private:
Contexts.back().IsExpression = true;
next();
if (CurrentToken)
- CurrentToken->SpacesRequiredBefore = true;
+ CurrentToken->SpacesRequiredBefore = 1;
parseLine();
break;
default:
@@ -2639,8 +2639,8 @@ private:
if (PreviousNotConst->is(TT_TemplateCloser)) {
return PreviousNotConst && PreviousNotConst->MatchingParen &&
PreviousNotConst->MatchingParen->Previous &&
- PreviousNotConst->MatchingParen->Previous->isNot(tok::period) &&
- PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);
+ !PreviousNotConst->MatchingParen->Previous->isOneOf(
+ tok::period, tok::kw_template);
}
if ((PreviousNotConst->is(tok::r_paren) &&
@@ -3369,7 +3369,7 @@ private:
Current->isOneOf(Keywords.kw_in, Keywords.kw_as)) {
return prec::Relational;
}
- if (Current->is(TT_BinaryOperator) || Current->is(tok::comma))
+ if (Current->isOneOf(TT_BinaryOperator, tok::comma))
return Current->getPrecedence();
if (Current->isOneOf(tok::period, tok::arrow) &&
Current->isNot(TT_TrailingReturnArrow)) {
@@ -4314,8 +4314,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(tok::coloncolon))
return Style.PenaltyBreakScopeResolution;
- if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
- Right.is(tok::kw_operator)) {
+ if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
+ tok::kw_operator)) {
if (Line.startsWith(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
return 3;
if (Left.is(TT_StartOfName))
@@ -4757,7 +4757,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Previous) {
if (Previous->endsSequence(tok::kw_operator))
return Style.PointerAlignment != FormatStyle::PAS_Left;
- if (Previous->is(tok::kw_const) || Previous->is(tok::kw_volatile)) {
+ if (Previous->isOneOf(tok::kw_const, tok::kw_volatile)) {
return (Style.PointerAlignment != FormatStyle::PAS_Left) ||
(Style.SpaceAroundPointerQualifiers ==
FormatStyle::SAPQ_After) ||
@@ -4931,8 +4931,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
}
if (Left.is(TT_TemplateCloser) && Left.MatchingParen &&
Left.MatchingParen->Previous &&
- (Left.MatchingParen->Previous->is(tok::period) ||
- Left.MatchingParen->Previous->is(tok::coloncolon))) {
+ Left.MatchingParen->Previous->isOneOf(tok::period, tok::coloncolon)) {
// Java call to generic function with explicit type:
// A.<B<C<...>>>DoSomething();
// A::<B<C<...>>>DoSomething(); // With a Java 8 method reference.
@@ -5207,8 +5206,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// (e.g. as "const x of y" in a for loop), or after a destructuring
// operation (const [x, y] of z, const {a, b} of c).
(Left.is(Keywords.kw_of) && BeforeLeft &&
- (BeforeLeft->is(tok::identifier) ||
- BeforeLeft->isOneOf(tok::r_square, tok::r_brace)))) &&
+ BeforeLeft->isOneOf(tok::identifier, tok::r_square, tok::r_brace))) &&
(!BeforeLeft || BeforeLeft->isNot(tok::period))) {
return true;
}
@@ -5516,7 +5514,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
}
if (Style.isJava() && Right.is(tok::coloncolon) &&
- (Left.is(tok::identifier) || Left.is(tok::kw_this))) {
+ Left.isOneOf(tok::identifier, tok::kw_this)) {
return false;
}
if (Right.is(tok::coloncolon) && Left.is(tok::identifier)) {
@@ -5587,8 +5585,8 @@ static bool IsFunctionArgument(const FormatToken &Tok) {
}
static bool
-isItAnEmptyLambdaAllowed(const FormatToken &Tok,
- FormatStyle::ShortLambdaStyle ShortLambdaOption) {
+isEmptyLambdaAllowed(const FormatToken &Tok,
+ FormatStyle::ShortLambdaStyle ShortLambdaOption) {
return Tok.Children.empty() && ShortLambdaOption != FormatStyle::SLS_None;
}
@@ -5808,8 +5806,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
}
if (Right.is(tok::comment)) {
- return Left.isNot(BK_BracedInit) && Left.isNot(TT_CtorInitializerColon) &&
- (Right.NewlinesBefore > 0 && Right.HasUnescapedNewline);
+ return !Left.isOneOf(BK_BracedInit, TT_CtorInitializerColon) &&
+ Right.NewlinesBefore > 0 && Right.HasUnescapedNewline;
}
if (Left.isTrailingComment())
return true;
@@ -5977,7 +5975,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
// Put multiple Java annotation on a new line.
if ((Style.isJava() || Style.isJavaScript()) &&
Left.is(TT_LeadingJavaAnnotation) &&
- Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
+ !Right.isOneOf(TT_LeadingJavaAnnotation, tok::l_paren) &&
(Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations)) {
return true;
}
@@ -6043,7 +6041,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
((LBrace->is(tok::l_brace) &&
(LBrace->is(TT_DictLiteral) ||
(LBrace->Next && LBrace->Next->is(tok::r_brace)))) ||
- LBrace->is(TT_ArrayInitializerLSquare) || LBrace->is(tok::less))) {
+ LBrace->isOneOf(TT_ArrayInitializerLSquare, tok::less))) {
// If Left.ParameterCount is 0, then this submessage entry is not the
// first in its parent submessage, and we want to break before this entry.
// If Left.ParameterCount is greater than 0, then its parent submessage
@@ -6257,9 +6255,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
}
if (Left.is(tok::question) && Right.is(tok::colon))
return false;
- if (Right.is(TT_ConditionalExpr) || Right.is(tok::question))
+ if (Right.isOneOf(TT_ConditionalExpr, tok::question))
return Style.BreakBeforeTernaryOperators;
- if (Left.is(TT_ConditionalExpr) || Left.is(tok::question))
+ if (Left.isOneOf(TT_ConditionalExpr, tok::question))
return !Style.BreakBeforeTernaryOperators;
if (Left.is(TT_InheritanceColon))
return Style.BreakInheritanceList == FormatStyle::BILS_AfterColon;
@@ -6302,7 +6300,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
// submessage: { ... }
// submessage: < ... >
// repeated: [ ... ]
- if (((Right.is(tok::l_brace) || Right.is(tok::less)) &&
+ if ((Right.isOneOf(tok::l_brace, tok::less) &&
Right.is(TT_DictLiteral)) ||
Right.is(TT_ArrayInitializerLSquare)) {
return false;
@@ -6352,10 +6350,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
Right.getPrecedence() != prec::Assignment)) {
return true;
}
- if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator) ||
- Left.is(tok::kw_operator)) {
+ if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator, tok::kw_operator))
return false;
- }
if (Left.is(tok::equal) && !Right.isOneOf(tok::kw_default, tok::kw_delete) &&
Line.Type == LT_VirtualFunctionDecl && Left.NestingLevel == 0) {
return false;
@@ -6440,9 +6436,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;
if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace)) {
if (isAllmanLambdaBrace(Left))
- return !isItAnEmptyLambdaAllowed(Left, ShortLambdaOption);
+ return !isEmptyLambdaAllowed(Left, ShortLambdaOption);
if (isAllmanLambdaBrace(Right))
- return !isItAnEmptyLambdaAllowed(Right, ShortLambdaOption);
+ return !isEmptyLambdaAllowed(Right, ShortLambdaOption);
}
if (Right.is(tok::kw_noexcept) && Right.is(TT_TrailingAnnotation)) {
diff --git a/clang/lib/Frontend/ASTMerge.cpp b/clang/lib/Frontend/ASTMerge.cpp
index a4ce883..10c1045 100644
--- a/clang/lib/Frontend/ASTMerge.cpp
+++ b/clang/lib/Frontend/ASTMerge.cpp
@@ -41,10 +41,10 @@ void ASTMergeAction::ExecuteAction() {
auto SharedState = std::make_shared<ASTImporterSharedState>(
*CI.getASTContext().getTranslationUnitDecl());
for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(new DiagnosticsEngine(
+ auto Diags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(
DiagIDs, CI.getDiagnosticOpts(),
new ForwardingDiagnosticConsumer(*CI.getDiagnostics().getClient()),
- /*ShouldOwnClient=*/true));
+ /*ShouldOwnClient=*/true);
std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile(
ASTFiles[I], CI.getPCHContainerReader(), ASTUnit::LoadEverything,
nullptr, Diags, CI.getFileSystemOpts(), CI.getHeaderSearchOpts());
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 67ed17b..a407825 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -831,11 +831,10 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->DiagOpts = DiagOpts;
AST->Diagnostics = Diags;
- AST->FileMgr = new FileManager(FileSystemOpts, VFS);
+ AST->FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOpts, VFS);
AST->UserFilesAreVolatile = UserFilesAreVolatile;
- AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
- AST->getFileManager(),
- UserFilesAreVolatile);
+ AST->SourceMgr = llvm::makeIntrusiveRefCnt<SourceManager>(
+ AST->getDiagnostics(), AST->getFileManager(), UserFilesAreVolatile);
AST->ModCache = createCrossProcessModuleCache();
AST->HSOpts = std::make_unique<HeaderSearchOptions>(HSOpts);
AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormats().front());
@@ -858,20 +857,20 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
Preprocessor &PP = *AST->PP;
if (ToLoad >= LoadASTOnly)
- AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(),
- PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo(),
- AST->getTranslationUnitKind());
+ AST->Ctx = llvm::makeIntrusiveRefCnt<ASTContext>(
+ *AST->LangOpts, AST->getSourceManager(), PP.getIdentifierTable(),
+ PP.getSelectorTable(), PP.getBuiltinInfo(),
+ AST->getTranslationUnitKind());
DisableValidationForModuleKind disableValid =
DisableValidationForModuleKind::None;
if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
disableValid = DisableValidationForModuleKind::All;
- AST->Reader = new ASTReader(PP, *AST->ModCache, AST->Ctx.get(),
- PCHContainerRdr, *AST->CodeGenOpts, {},
- /*isysroot=*/"",
- /*DisableValidationKind=*/disableValid,
- AllowASTWithCompilerErrors);
+ AST->Reader = llvm::makeIntrusiveRefCnt<ASTReader>(
+ PP, *AST->ModCache, AST->Ctx.get(), PCHContainerRdr, *AST->CodeGenOpts,
+ ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
+ /*isysroot=*/"",
+ /*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors);
unsigned Counter = 0;
AST->Reader->setListener(std::make_unique<ASTInfoCollector>(
@@ -1191,9 +1190,11 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// changed above in AddImplicitPreamble. If VFS is nullptr, rely on
// createFileManager to create one.
if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS)
- Clang->setFileManager(&*FileMgr);
- else
- FileMgr = Clang->createFileManager(std::move(VFS));
+ Clang->setFileManager(FileMgr);
+ else {
+ Clang->createFileManager(std::move(VFS));
+ FileMgr = Clang->getFileManagerPtr();
+ }
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
@@ -1204,7 +1205,7 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// Set up diagnostics, capturing any diagnostics that would
// otherwise be dropped.
- Clang->setDiagnostics(&getDiagnostics());
+ Clang->setDiagnostics(getDiagnosticsPtr());
// Create the target instance.
if (!Clang->createTarget())
@@ -1226,15 +1227,15 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ResetForParse();
- SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
- UserFilesAreVolatile);
+ SourceMgr = llvm::makeIntrusiveRefCnt<SourceManager>(
+ getDiagnostics(), *FileMgr, +UserFilesAreVolatile);
if (!OverrideMainBuffer) {
checkAndRemoveNonDriverDiags(StoredDiagnostics);
TopLevelDeclsInPreamble.clear();
}
// Create the source manager.
- Clang->setSourceManager(&getSourceManager());
+ Clang->setSourceManager(getSourceManagerPtr());
// If the main file has been overridden due to the use of a preamble,
// make that override happen and introduce the preamble.
@@ -1424,7 +1425,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true;
llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(
- PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,
+ PreambleInvocationIn, MainFileBuffer.get(), Bounds, Diagnostics, VFS,
PCHContainerOps, StorePreamblesInMemory, PreambleStoragePath,
Callbacks);
@@ -1499,13 +1500,13 @@ void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
TheSema = CI.takeSema();
Consumer = CI.takeASTConsumer();
if (CI.hasASTContext())
- Ctx = &CI.getASTContext();
+ Ctx = CI.getASTContextPtr();
if (CI.hasPreprocessor())
PP = CI.getPreprocessorPtr();
CI.setSourceManager(nullptr);
CI.setFileManager(nullptr);
if (CI.hasTarget())
- Target = &CI.getTarget();
+ Target = CI.getTargetPtr();
Reader = CI.getASTReader();
HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();
if (Invocation != CI.getInvocationPtr()) {
@@ -1555,10 +1556,11 @@ ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
AST->Invocation = std::move(CI);
- AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
+ AST->FileMgr =
+ llvm::makeIntrusiveRefCnt<FileManager>(AST->FileSystemOpts, VFS);
AST->UserFilesAreVolatile = UserFilesAreVolatile;
- AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
- UserFilesAreVolatile);
+ AST->SourceMgr = llvm::makeIntrusiveRefCnt<SourceManager>(
+ AST->getDiagnostics(), *AST->FileMgr, UserFilesAreVolatile);
AST->ModCache = createCrossProcessModuleCache();
return AST;
@@ -1624,7 +1626,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
// Set up diagnostics, capturing any diagnostics that would
// otherwise be dropped.
- Clang->setDiagnostics(&AST->getDiagnostics());
+ Clang->setDiagnostics(AST->getDiagnosticsPtr());
// Create the target instance.
if (!Clang->createTarget())
@@ -1646,10 +1648,10 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
AST->Reader = nullptr;
// Create a file manager object to provide access to and cache the filesystem.
- Clang->setFileManager(&AST->getFileManager());
+ Clang->setFileManager(AST->getFileManagerPtr());
// Create the source manager.
- Clang->setSourceManager(&AST->getSourceManager());
+ Clang->setSourceManager(AST->getSourceManagerPtr());
FrontendAction *Act = Action;
@@ -1743,8 +1745,9 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
std::shared_ptr<CompilerInvocation> CI,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::shared_ptr<DiagnosticOptions> DiagOpts,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr,
- bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ IntrusiveRefCntPtr<FileManager> FileMgr, bool OnlyLocalDecls,
+ CaptureDiagsKind CaptureDiagnostics,
unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
bool UserFilesAreVolatile) {
@@ -1773,7 +1776,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
PrecompilePreambleAfterNParses,
- &AST->FileMgr->getVirtualFileSystem()))
+ AST->FileMgr->getVirtualFileSystemPtr()))
return nullptr;
return AST;
}
@@ -1849,7 +1852,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(
AST->FileSystemOpts = CI->getFileSystemOpts();
AST->CodeGenOpts = std::make_unique<CodeGenOptions>(CI->getCodeGenOpts());
VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
- AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
+ AST->FileMgr =
+ llvm::makeIntrusiveRefCnt<FileManager>(AST->FileSystemOpts, VFS);
AST->StorePreamblesInMemory = StorePreamblesInMemory;
AST->PreambleStoragePath = PreambleStoragePath;
AST->ModCache = createCrossProcessModuleCache();
@@ -1895,7 +1899,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
if (!VFS) {
assert(FileMgr && "FileMgr is null on Reparse call");
- VFS = &FileMgr->getVirtualFileSystem();
+ VFS = FileMgr->getVirtualFileSystemPtr();
}
clearFileLevelDecls();
@@ -2209,8 +2213,10 @@ void ASTUnit::CodeComplete(
bool IncludeCodePatterns, bool IncludeBriefComments,
CodeCompleteConsumer &Consumer,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr,
- FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diag, LangOptions &LangOpts,
+ llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr,
+ llvm::IntrusiveRefCntPtr<FileManager> FileMgr,
+ SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers,
std::unique_ptr<SyntaxOnlyAction> Act) {
if (!Invocation)
@@ -2259,12 +2265,12 @@ void ASTUnit::CodeComplete(
std::string(Clang->getFrontendOpts().Inputs[0].getFile());
// Set up diagnostics, capturing any diagnostics produced.
- Clang->setDiagnostics(&Diag);
+ Clang->setDiagnostics(Diag);
CaptureDroppedDiagnostics Capture(CaptureDiagsKind::All,
Clang->getDiagnostics(),
&StoredDiagnostics, nullptr);
- ProcessWarningOptions(Diag, Inv.getDiagnosticOpts(),
- FileMgr.getVirtualFileSystem());
+ ProcessWarningOptions(*Diag, Inv.getDiagnosticOpts(),
+ FileMgr->getVirtualFileSystem());
// Create the target instance.
if (!Clang->createTarget()) {
@@ -2281,8 +2287,8 @@ void ASTUnit::CodeComplete(
"IR inputs not support here!");
// Use the source and file managers that we were given.
- Clang->setFileManager(&FileMgr);
- Clang->setSourceManager(&SourceMgr);
+ Clang->setFileManager(FileMgr);
+ Clang->setSourceManager(SourceMgr);
// Remap files.
PreprocessorOpts.clearRemappedFiles();
@@ -2300,7 +2306,7 @@ void ASTUnit::CodeComplete(
auto getUniqueID =
[&FileMgr](StringRef Filename) -> std::optional<llvm::sys::fs::UniqueID> {
- if (auto Status = FileMgr.getVirtualFileSystem().status(Filename))
+ if (auto Status = FileMgr->getVirtualFileSystem().status(Filename))
return Status->getUniqueID();
return std::nullopt;
};
@@ -2321,7 +2327,8 @@ void ASTUnit::CodeComplete(
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
if (Preamble && Line > 1 && hasSameUniqueID(File, OriginalSourceFile)) {
OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(
- PCHContainerOps, Inv, &FileMgr.getVirtualFileSystem(), false, Line - 1);
+ PCHContainerOps, Inv, FileMgr->getVirtualFileSystemPtr(), false,
+ Line - 1);
}
// If the main file has been overridden due to the use of a preamble,
@@ -2331,7 +2338,7 @@ void ASTUnit::CodeComplete(
"No preamble was built, but OverrideMainBuffer is not null");
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
- &FileMgr.getVirtualFileSystem();
+ FileMgr->getVirtualFileSystemPtr();
Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS,
OverrideMainBuffer.get());
// FIXME: there is no way to update VFS if it was changed by
diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp
index ba7c767..013814a 100644
--- a/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -53,17 +53,17 @@ private:
};
} // end anonymous namespace
-static ASTReader *
+static llvm::IntrusiveRefCntPtr<ASTReader>
createASTReader(CompilerInstance &CI, StringRef pchFile,
SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> &MemBufs,
SmallVectorImpl<std::string> &bufNames,
ASTDeserializationListener *deserialListener = nullptr) {
Preprocessor &PP = CI.getPreprocessor();
- std::unique_ptr<ASTReader> Reader;
- Reader.reset(new ASTReader(
+ auto Reader = llvm::makeIntrusiveRefCnt<ASTReader>(
PP, CI.getModuleCache(), &CI.getASTContext(), CI.getPCHContainerReader(),
- CI.getCodeGenOpts(), /*Extensions=*/{},
- /*isysroot=*/"", DisableValidationForModuleKind::PCH));
+ CI.getCodeGenOpts(),
+ /*Extensions=*/ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
+ /*isysroot=*/"", DisableValidationForModuleKind::PCH);
for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
StringRef sr(bufNames[ti]);
Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti]));
@@ -74,7 +74,7 @@ createASTReader(CompilerInstance &CI, StringRef pchFile,
case ASTReader::Success:
// Set the predefines buffer as suggested by the PCH reader.
PP.setPredefines(Reader->getSuggestedPredefines());
- return Reader.release();
+ return Reader;
case ASTReader::Failure:
case ASTReader::Missing:
@@ -87,8 +87,9 @@ createASTReader(CompilerInstance &CI, StringRef pchFile,
return nullptr;
}
-IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
- CompilerInstance &CI, IntrusiveRefCntPtr<ExternalSemaSource> &Reader) {
+IntrusiveRefCntPtr<ExternalSemaSource>
+clang::createChainedIncludesSource(CompilerInstance &CI,
+ IntrusiveRefCntPtr<ASTReader> &OutReader) {
std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes;
assert(!includes.empty() && "No '-chain-include' in options!");
@@ -118,13 +119,12 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
TextDiagnosticPrinter *DiagClient =
new TextDiagnosticPrinter(llvm::errs(), CI.getDiagnosticOpts());
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, CI.getDiagnosticOpts(), DiagClient));
+ auto Diags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(
+ DiagnosticIDs::create(), CI.getDiagnosticOpts(), DiagClient);
auto Clang = std::make_unique<CompilerInstance>(
std::move(CInvok), CI.getPCHContainerOperations());
- Clang->setDiagnostics(Diags.get());
+ Clang->setDiagnostics(Diags);
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().getTargetOpts()));
Clang->createFileManager();
@@ -187,12 +187,12 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
assert(!SerialBufs.empty());
std::string pchName = includes.back() + ".pch-final";
serialBufNames.push_back(pchName);
- Reader = createASTReader(CI, pchName, SerialBufs, serialBufNames);
- if (!Reader)
+ OutReader = createASTReader(CI, pchName, SerialBufs, serialBufNames);
+ if (!OutReader)
return nullptr;
auto ChainedSrc =
llvm::makeIntrusiveRefCnt<ChainedIncludesSource>(std::move(CIs));
return llvm::makeIntrusiveRefCnt<MultiplexExternalSemaSource>(
- ChainedSrc.get(), Reader.get());
+ std::move(ChainedSrc), OutReader);
}
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index c7b82db..d64290f 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -87,8 +87,9 @@ bool CompilerInstance::shouldBuildGlobalModuleIndex() const {
!DisableGeneratingGlobalModuleIndex;
}
-void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
- Diagnostics = Value;
+void CompilerInstance::setDiagnostics(
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Value) {
+ Diagnostics = std::move(Value);
}
void CompilerInstance::setVerboseOutputStream(raw_ostream &Value) {
@@ -160,20 +161,28 @@ llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const {
return getFileManager().getVirtualFileSystem();
}
-void CompilerInstance::setFileManager(FileManager *Value) {
- FileMgr = Value;
+llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+CompilerInstance::getVirtualFileSystemPtr() const {
+ return getFileManager().getVirtualFileSystemPtr();
}
-void CompilerInstance::setSourceManager(SourceManager *Value) {
- SourceMgr = Value;
+void CompilerInstance::setFileManager(
+ llvm::IntrusiveRefCntPtr<FileManager> Value) {
+ FileMgr = std::move(Value);
+}
+
+void CompilerInstance::setSourceManager(
+ llvm::IntrusiveRefCntPtr<SourceManager> Value) {
+ SourceMgr = std::move(Value);
}
void CompilerInstance::setPreprocessor(std::shared_ptr<Preprocessor> Value) {
PP = std::move(Value);
}
-void CompilerInstance::setASTContext(ASTContext *Value) {
- Context = Value;
+void CompilerInstance::setASTContext(
+ llvm::IntrusiveRefCntPtr<ASTContext> Value) {
+ Context = std::move(Value);
if (Context && Consumer)
getASTConsumer().Initialize(getASTContext());
@@ -340,9 +349,8 @@ IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
llvm::vfs::FileSystem &VFS, DiagnosticOptions &Opts,
DiagnosticConsumer *Client, bool ShouldOwnClient,
const CodeGenOptions *CodeGenOpts) {
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, Opts));
+ auto Diags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(
+ DiagnosticIDs::create(), Opts);
// Create the diagnostic client for reporting errors or for
// implementing -verify.
@@ -375,21 +383,23 @@ IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
FileManager *CompilerInstance::createFileManager(
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
if (!VFS)
- VFS = FileMgr ? &FileMgr->getVirtualFileSystem()
+ VFS = FileMgr ? FileMgr->getVirtualFileSystemPtr()
: createVFSFromCompilerInvocation(getInvocation(),
getDiagnostics());
assert(VFS && "FileManager has no VFS?");
if (getFrontendOpts().ShowStats)
VFS =
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(VFS));
- FileMgr = new FileManager(getFileSystemOpts(), std::move(VFS));
+ FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(getFileSystemOpts(),
+ std::move(VFS));
return FileMgr.get();
}
// Source Manager
void CompilerInstance::createSourceManager(FileManager &FileMgr) {
- SourceMgr = new SourceManager(getDiagnostics(), FileMgr);
+ SourceMgr =
+ llvm::makeIntrusiveRefCnt<SourceManager>(getDiagnostics(), FileMgr);
}
// Initialize the remapping of files to alternative contents, e.g.,
@@ -549,11 +559,11 @@ std::string CompilerInstance::getSpecificModuleCachePath(StringRef ModuleHash) {
void CompilerInstance::createASTContext() {
Preprocessor &PP = getPreprocessor();
- auto *Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
- PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo(), PP.TUKind);
+ auto Context = llvm::makeIntrusiveRefCnt<ASTContext>(
+ getLangOpts(), PP.getSourceManager(), PP.getIdentifierTable(),
+ PP.getSelectorTable(), PP.getBuiltinInfo(), PP.TUKind);
Context->InitBuiltinTypes(getTarget(), getAuxTarget());
- setASTContext(Context);
+ setASTContext(std::move(Context));
}
// ExternalASTSource
@@ -633,17 +643,17 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
const HeaderSearchOptions &HSOpts =
PP.getHeaderSearchInfo().getHeaderSearchOpts();
- IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader(
+ auto Reader = llvm::makeIntrusiveRefCnt<ASTReader>(
PP, ModCache, &Context, PCHContainerRdr, CodeGenOpts, Extensions,
Sysroot.empty() ? "" : Sysroot.data(), DisableValidation,
AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false,
HSOpts.ModulesValidateSystemHeaders,
HSOpts.ModulesForceValidateUserHeaders,
- HSOpts.ValidateASTInputFilesContent, UseGlobalModuleIndex));
+ HSOpts.ValidateASTInputFilesContent, UseGlobalModuleIndex);
// We need the external source to be set up before we read the AST, because
// eagerly-deserialized declarations may use it.
- Context.setExternalSource(Reader.get());
+ Context.setExternalSource(Reader);
Reader->setDeserializationListener(
static_cast<ASTDeserializationListener *>(DeserializationListener),
@@ -750,7 +760,7 @@ void CompilerInstance::createSema(TranslationUnitKind TUKind,
// Attach the external sema source if there is any.
if (ExternalSemaSrc) {
- TheSema->addExternalSource(ExternalSemaSrc.get());
+ TheSema->addExternalSource(ExternalSemaSrc);
ExternalSemaSrc->InitializeSema(*TheSema);
}
@@ -1216,9 +1226,9 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompileImpl(
if (ThreadSafeConfig) {
Instance.createFileManager(ThreadSafeConfig->getVFS());
} else if (FrontendOpts.ModulesShareFileManager) {
- Instance.setFileManager(&getFileManager());
+ Instance.setFileManager(getFileManagerPtr());
} else {
- Instance.createFileManager(&getVirtualFileSystem());
+ Instance.createFileManager(getVirtualFileSystemPtr());
}
if (ThreadSafeConfig) {
@@ -1745,17 +1755,18 @@ void CompilerInstance::createASTReader() {
if (timerGroup)
ReadTimer = std::make_unique<llvm::Timer>("reading_modules",
"Reading modules", *timerGroup);
- TheASTReader = new ASTReader(
+ TheASTReader = llvm::makeIntrusiveRefCnt<ASTReader>(
getPreprocessor(), getModuleCache(), &getASTContext(),
getPCHContainerReader(), getCodeGenOpts(),
getFrontendOpts().ModuleFileExtensions,
Sysroot.empty() ? "" : Sysroot.c_str(),
PPOpts.DisablePCHOrModuleValidation,
/*AllowASTWithCompilerErrors=*/FEOpts.AllowPCMWithCompilerErrors,
- /*AllowConfigurationMismatch=*/false, HSOpts.ModulesValidateSystemHeaders,
- HSOpts.ModulesForceValidateUserHeaders,
- HSOpts.ValidateASTInputFilesContent,
- getFrontendOpts().UseGlobalModuleIndex, std::move(ReadTimer));
+ /*AllowConfigurationMismatch=*/false,
+ +HSOpts.ModulesValidateSystemHeaders,
+ +HSOpts.ModulesForceValidateUserHeaders,
+ +HSOpts.ValidateASTInputFilesContent,
+ +getFrontendOpts().UseGlobalModuleIndex, std::move(ReadTimer));
if (hasASTConsumer()) {
TheASTReader->setDeserializationListener(
getASTConsumer().GetASTDeserializationListener());
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index ab4384a..9f77e62 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -826,7 +826,7 @@ static bool RoundTrip(ParseFn Parse, GenerateFn Generate,
// Setup a dummy DiagnosticsEngine.
DiagnosticOptions DummyDiagOpts;
- DiagnosticsEngine DummyDiags(new DiagnosticIDs(), DummyDiagOpts);
+ DiagnosticsEngine DummyDiags(DiagnosticIDs::create(), DummyDiagOpts);
DummyDiags.setClient(new TextDiagnosticBuffer());
// Run the first parse on the original arguments with the dummy invocation and
@@ -2685,7 +2685,7 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
std::optional<DiagnosticsEngine> IgnoringDiags;
if (!Diags) {
IgnoringDiagOpts.emplace();
- IgnoringDiags.emplace(new DiagnosticIDs(), *IgnoringDiagOpts,
+ IgnoringDiags.emplace(DiagnosticIDs::create(), *IgnoringDiagOpts,
new IgnoringDiagConsumer());
Diags = &*IgnoringDiags;
}
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 1d82fc7..2d69f8c 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -9,6 +9,7 @@
#include "clang/Frontend/FrontendAction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticOptions.h"
@@ -39,6 +40,7 @@
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/ErrorHandling.h"
@@ -87,12 +89,25 @@ public:
// reducing the granularity and making the output less useful.
return;
}
- if (auto *DC = D->getDeclContext(); !DC || !DC->isFileContext()) {
+ auto *DC = D->getLexicalDeclContext();
+ if (!DC || !DC->isFileContext()) {
// We choose to work at namespace level to reduce complexity and the
// number of cases we care about.
return;
}
+
PendingDecls.push_back(D);
+ if (auto *NS = dyn_cast<NamespaceDecl>(DC)) {
+ // Add any namespaces we have not seen before.
+ // Note that we filter out namespaces from DeclRead as it includes too
+ // all redeclarations and we only want the ones that had other used
+ // declarations.
+ while (NS && ProcessedNamespaces.insert(NS).second) {
+ PendingDecls.push_back(NS);
+
+ NS = dyn_cast<NamespaceDecl>(NS->getLexicalParent());
+ }
+ }
}
struct Position {
@@ -141,23 +156,25 @@ public:
OptionalFileEntryRef Ref;
};
llvm::DenseMap<const FileEntry *, FileData> FileToRanges;
+
for (const Decl *D : PendingDecls) {
- CharSourceRange R = SM.getExpansionRange(D->getSourceRange());
- if (!R.isValid())
- continue;
+ for (CharSourceRange R : getRangesToMark(D)) {
+ if (!R.isValid())
+ continue;
- auto *F = SM.getFileEntryForID(SM.getFileID(R.getBegin()));
- if (F != SM.getFileEntryForID(SM.getFileID(R.getEnd()))) {
- // Such cases are rare and difficult to handle.
- continue;
- }
+ auto *F = SM.getFileEntryForID(SM.getFileID(R.getBegin()));
+ if (F != SM.getFileEntryForID(SM.getFileID(R.getEnd()))) {
+ // Such cases are rare and difficult to handle.
+ continue;
+ }
- auto &Data = FileToRanges[F];
- if (!Data.Ref)
- Data.Ref = SM.getFileEntryRefForID(SM.getFileID(R.getBegin()));
- Data.FromTo.push_back(
- {Position::GetBeginSpelling(SM, R),
- Position::GetEndSpelling(SM, R, D->getLangOpts())});
+ auto &Data = FileToRanges[F];
+ if (!Data.Ref)
+ Data.Ref = SM.getFileEntryRefForID(SM.getFileID(R.getBegin()));
+ Data.FromTo.push_back(
+ {Position::GetBeginSpelling(SM, R),
+ Position::GetEndSpelling(SM, R, D->getLangOpts())});
+ }
}
// To simplify output, merge consecutive and intersecting ranges.
@@ -188,10 +205,49 @@ public:
private:
std::vector<const Decl *> PendingDecls;
+ llvm::SmallPtrSet<const NamespaceDecl *, 0> ProcessedNamespaces;
bool IsCollectingDecls = true;
const SourceManager &SM;
std::unique_ptr<llvm::raw_ostream> OS;
+ llvm::SmallVector<CharSourceRange, 2> getRangesToMark(const Decl *D) {
+ auto *NS = dyn_cast<NamespaceDecl>(D);
+ if (!NS)
+ return {SM.getExpansionRange(D->getSourceRange())};
+
+ SourceLocation LBraceLoc;
+ if (NS->isAnonymousNamespace()) {
+ LBraceLoc = NS->getLocation();
+ } else {
+ // Start with the location of the identifier.
+ SourceLocation TokenBeforeLBrace = NS->getLocation();
+ if (NS->hasAttrs()) {
+ for (auto *A : NS->getAttrs()) {
+ // But attributes may go after it.
+ if (SM.isBeforeInTranslationUnit(TokenBeforeLBrace,
+ A->getRange().getEnd())) {
+ // Give up, the attributes are often coming from macros and we
+ // cannot skip them reliably.
+ return {};
+ }
+ }
+ }
+ auto &LangOpts = D->getLangOpts();
+ // Now skip one token, the next should be the lbrace.
+ Token Tok;
+ if (Lexer::getRawToken(TokenBeforeLBrace, Tok, SM, LangOpts, true) ||
+ Lexer::getRawToken(Tok.getEndLoc(), Tok, SM, LangOpts, true) ||
+ Tok.getKind() != tok::l_brace) {
+ // On error or if we did not find the token we expected, avoid marking
+ // everything inside the namespace as used.
+ return {};
+ }
+ LBraceLoc = Tok.getLocation();
+ }
+ return {SM.getExpansionRange(SourceRange(NS->getBeginLoc(), LBraceLoc)),
+ SM.getExpansionRange(NS->getRBraceLoc())};
+ }
+
void printJson(llvm::ArrayRef<RequiredRanges> Result) {
*OS << "{\n";
*OS << R"( "required_ranges": [)" << "\n";
@@ -226,6 +282,8 @@ private:
}
*OS << " ]\n";
*OS << "}\n";
+
+ OS->flush();
}
};
@@ -763,11 +821,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// If we're replaying the build of an AST file, import it and set up
// the initial state from its build.
if (ReplayASTFile) {
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CI.getDiagnosticsPtr();
// The AST unit populates its own diagnostics engine rather than ours.
- IntrusiveRefCntPtr<DiagnosticsEngine> ASTDiags(new DiagnosticsEngine(
- Diags->getDiagnosticIDs(), Diags->getDiagnosticOptions()));
+ auto ASTDiags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(
+ Diags->getDiagnosticIDs(), Diags->getDiagnosticOptions());
ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);
// FIXME: What if the input is a memory buffer?
@@ -787,7 +845,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// Set the shared objects, these are reset when we finish processing the
// file, otherwise the CompilerInstance will happily destroy them.
- CI.setFileManager(&AST->getFileManager());
+ CI.setFileManager(AST->getFileManagerPtr());
CI.createSourceManager(CI.getFileManager());
CI.getSourceManager().initializeForReplay(AST->getSourceManager());
@@ -835,7 +893,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
assert(hasASTFileSupport() &&
"This action does not have AST file support!");
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CI.getDiagnosticsPtr();
// FIXME: What if the input is a memory buffer?
StringRef InputFile = Input.getFile();
@@ -854,13 +912,13 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// Set the shared objects, these are reset when we finish processing the
// file, otherwise the CompilerInstance will happily destroy them.
- CI.setFileManager(&AST->getFileManager());
- CI.setSourceManager(&AST->getSourceManager());
+ CI.setFileManager(AST->getFileManagerPtr());
+ CI.setSourceManager(AST->getSourceManagerPtr());
CI.setPreprocessor(AST->getPreprocessorPtr());
Preprocessor &PP = CI.getPreprocessor();
PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
PP.getLangOpts());
- CI.setASTContext(&AST->getASTContext());
+ CI.setASTContext(AST->getASTContextPtr());
setCurrentInput(Input, std::move(AST));
@@ -1114,11 +1172,12 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {
// Convert headers to PCH and chain them.
- IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader;
+ IntrusiveRefCntPtr<ExternalSemaSource> source;
+ IntrusiveRefCntPtr<ASTReader> FinalReader;
source = createChainedIncludesSource(CI, FinalReader);
if (!source)
return false;
- CI.setASTReader(static_cast<ASTReader *>(FinalReader.get()));
+ CI.setASTReader(FinalReader);
CI.getASTContext().setExternalSource(source);
} else if (CI.getLangOpts().Modules ||
!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
@@ -1194,23 +1253,21 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// provides the layouts from that file.
if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() &&
CI.hasASTContext() && !CI.getASTContext().getExternalSource()) {
- IntrusiveRefCntPtr<ExternalASTSource>
- Override(new LayoutOverrideSource(
- CI.getFrontendOpts().OverrideRecordLayoutsFile));
+ auto Override = llvm::makeIntrusiveRefCnt<LayoutOverrideSource>(
+ CI.getFrontendOpts().OverrideRecordLayoutsFile);
CI.getASTContext().setExternalSource(Override);
}
// Setup HLSL External Sema Source
if (CI.getLangOpts().HLSL && CI.hasASTContext()) {
- IntrusiveRefCntPtr<ExternalSemaSource> HLSLSema(
- new HLSLExternalSemaSource());
- if (auto *SemaSource = dyn_cast_if_present<ExternalSemaSource>(
- CI.getASTContext().getExternalSource())) {
- IntrusiveRefCntPtr<ExternalSemaSource> MultiSema(
- new MultiplexExternalSemaSource(SemaSource, HLSLSema.get()));
- CI.getASTContext().setExternalSource(MultiSema);
+ auto HLSLSema = llvm::makeIntrusiveRefCnt<HLSLExternalSemaSource>();
+ if (auto SemaSource = dyn_cast_if_present<ExternalSemaSource>(
+ CI.getASTContext().getExternalSourcePtr())) {
+ auto MultiSema = llvm::makeIntrusiveRefCnt<MultiplexExternalSemaSource>(
+ std::move(SemaSource), std::move(HLSLSema));
+ CI.getASTContext().setExternalSource(std::move(MultiSema));
} else
- CI.getASTContext().setExternalSource(HLSLSema);
+ CI.getASTContext().setExternalSource(std::move(HLSLSema));
}
FailureCleanup.release();
diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp
index 146cf90..03f70b7 100644
--- a/clang/lib/Frontend/PrecompiledPreamble.cpp
+++ b/clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -57,11 +57,9 @@ createVFSOverlayForPreamblePCH(StringRef PCHFilename,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
// We want only the PCH file from the real filesystem to be available,
// so we create an in-memory VFS with just that and overlay it on top.
- IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> PCHFS(
- new llvm::vfs::InMemoryFileSystem());
+ auto PCHFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
PCHFS->addFile(PCHFilename, 0, std::move(PCHBuffer));
- IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> Overlay(
- new llvm::vfs::OverlayFileSystem(VFS));
+ auto Overlay = llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(VFS);
Overlay->pushOverlay(PCHFS);
return Overlay;
}
@@ -414,7 +412,7 @@ PrecompiledPreamble::operator=(PrecompiledPreamble &&) = default;
llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
const CompilerInvocation &Invocation,
const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
- DiagnosticsEngine &Diagnostics,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps, bool StoreInMemory,
StringRef StoragePath, PreambleCallbacks &Callbacks) {
@@ -463,7 +461,7 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> CICleanup(
Clang.get());
- Clang->setDiagnostics(&Diagnostics);
+ Clang->setDiagnostics(Diagnostics);
// Create the target instance.
if (!Clang->createTarget())
@@ -478,18 +476,19 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
}
// Clear out old caches and data.
- Diagnostics.Reset();
- ProcessWarningOptions(Diagnostics, Clang->getDiagnosticOpts(), *VFS);
+ Diagnostics->Reset();
+ ProcessWarningOptions(*Diagnostics, Clang->getDiagnosticOpts(), *VFS);
- VFS =
- createVFSFromCompilerInvocation(Clang->getInvocation(), Diagnostics, VFS);
+ VFS = createVFSFromCompilerInvocation(Clang->getInvocation(), *Diagnostics,
+ VFS);
// Create a file manager object to provide access to and cache the filesystem.
- Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS));
+ Clang->setFileManager(
+ llvm::makeIntrusiveRefCnt<FileManager>(Clang->getFileSystemOpts(), VFS));
// Create the source manager.
- Clang->setSourceManager(
- new SourceManager(Diagnostics, Clang->getFileManager()));
+ Clang->setSourceManager(llvm::makeIntrusiveRefCnt<SourceManager>(
+ *Diagnostics, Clang->getFileManager()));
auto PreambleDepCollector = std::make_shared<PreambleDependencyCollector>();
Clang->addDependencyCollector(PreambleDepCollector);
diff --git a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 23a1f90..1f5bb47 100644
--- a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -753,10 +753,9 @@ DiagnosticsEngine *SDiagsWriter::getMetaDiags() {
// to be distinct from the engine the writer was being added to and would
// normally not be used.
if (!State->MetaDiagnostics) {
- IntrusiveRefCntPtr<DiagnosticIDs> IDs(new DiagnosticIDs());
auto Client = new TextDiagnosticPrinter(llvm::errs(), State->DiagOpts);
- State->MetaDiagnostics =
- std::make_unique<DiagnosticsEngine>(IDs, State->DiagOpts, Client);
+ State->MetaDiagnostics = std::make_unique<DiagnosticsEngine>(
+ DiagnosticIDs::create(), State->DiagOpts, Client);
}
return State->MetaDiagnostics.get();
}
diff --git a/clang/lib/Headers/__clang_cuda_runtime_wrapper.h b/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
index 44934ba..b1e5924 100644
--- a/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
+++ b/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
@@ -385,7 +385,12 @@ __host__ __device__ void __nv_tex_surf_handler(const char *name, T *ptr,
#endif // CUDA_VERSION
#endif // __cplusplus >= 201103L && CUDA_VERSION >= 9000
#include "surface_indirect_functions.h"
+#if CUDA_VERSION < 13000
+// Direct texture fetch functions had been deprecated since CUDA-11.
+// The file in CUDA-12 only carried unused texture types, and is no longer
+// needed.
#include "texture_fetch_functions.h"
+#endif // CUDA_VERSION < 13000
#include "texture_indirect_functions.h"
// Restore state of __CUDA_ARCH__ and __THROW we had on entry.
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
index e8ccccb..c877234 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
@@ -12,7 +12,7 @@
namespace hlsl {
namespace __detail {
-constexpr vector<uint, 4> d3d_color_to_ubyte4_impl(vector<float, 4> V) {
+constexpr int4 d3d_color_to_ubyte4_impl(float4 V) {
// Use the same scaling factor used by FXC, and DXC for DXIL
// (i.e., 255.001953)
// https://github.com/microsoft/DirectXShaderCompiler/blob/070d0d5a2beacef9eeb51037a9b04665716fd6f3/lib/HLSL/HLOperationLower.cpp#L666C1-L697C2
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 499a053..d9d87c8 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -418,7 +418,7 @@ const inline float4 lit(float NDotL, float NDotH, float M) {
/// This function swizzles and scales components of the \a x parameter. Use this
/// function to compensate for the lack of UBYTE4 support in some hardware.
-constexpr vector<uint, 4> D3DCOLORtoUBYTE4(vector<float, 4> V) {
+constexpr int4 D3DCOLORtoUBYTE4(float4 V) {
return __detail::d3d_color_to_ubyte4_impl(V);
}
diff --git a/clang/lib/Interpreter/CodeCompletion.cpp b/clang/lib/Interpreter/CodeCompletion.cpp
index dac3888..dc7030c 100644
--- a/clang/lib/Interpreter/CodeCompletion.cpp
+++ b/clang/lib/Interpreter/CodeCompletion.cpp
@@ -238,11 +238,9 @@ public:
// compiler instance before the super `ExecuteAction` triggers parsing
void IncrementalSyntaxOnlyAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
- ExternalSource *myExternalSource =
- new ExternalSource(CI.getASTContext(), CI.getFileManager(),
- ParentCI->getASTContext(), ParentCI->getFileManager());
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> astContextExternalSource(
- myExternalSource);
+ auto astContextExternalSource = llvm::makeIntrusiveRefCnt<ExternalSource>(
+ CI.getASTContext(), CI.getFileManager(), ParentCI->getASTContext(),
+ ParentCI->getFileManager());
CI.getASTContext().setExternalSource(astContextExternalSource);
CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage(
true);
@@ -380,9 +378,9 @@ void ReplCodeCompleter::codeComplete(CompilerInstance *InterpCI,
AU->setOwnsRemappedFileBuffers(false);
AU->CodeComplete(CodeCompletionFileName, 1, Col, RemappedFiles, false, false,
false, consumer,
- std::make_shared<clang::PCHContainerOperations>(), *diag,
- InterpCI->getLangOpts(), AU->getSourceManager(),
- AU->getFileManager(), sd, tb, std::move(Act));
+ std::make_shared<clang::PCHContainerOperations>(), diag,
+ InterpCI->getLangOpts(), AU->getSourceManagerPtr(),
+ AU->getFileManagerPtr(), sd, tb, std::move(Act));
}
} // namespace clang
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 9b71486..5e5ae81 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -86,7 +86,6 @@ GetCC1Arguments(DiagnosticsEngine *Diagnostics,
static llvm::Expected<std::unique_ptr<CompilerInstance>>
CreateCI(const llvm::opt::ArgStringList &Argv) {
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
// Register the support for object-file-wrapped Clang modules.
// FIXME: Clang should register these container operations automatically.
@@ -98,7 +97,7 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
// a well formed diagnostic object.
DiagnosticOptions DiagOpts;
TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
- DiagnosticsEngine Diags(DiagID, DiagOpts, DiagsBuffer);
+ DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagsBuffer);
bool Success = CompilerInvocation::CreateFromArgs(
Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);
@@ -174,11 +173,10 @@ IncrementalCompilerBuilder::create(std::string TT,
// Buffer diagnostics from argument parsing so that we can output them using a
// well formed diagnostic object.
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
std::unique_ptr<DiagnosticOptions> DiagOpts =
CreateAndPopulateDiagOpts(ClangArgv);
TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
- DiagnosticsEngine Diags(DiagID, *DiagOpts, DiagsBuffer);
+ DiagnosticsEngine Diags(DiagnosticIDs::create(), *DiagOpts, DiagsBuffer);
driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags);
Driver.setCheckInputsExist(false); // the input comes from mem buffers
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 829c81b..35ad0b5 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -503,8 +503,12 @@ static bool areAllValuesNoReturn(const VarDecl *VD, const CFGBlock &VarBlk,
TransferFunctions TF(VD);
BackwardDataflowWorklist Worklist(*AC.getCFG(), AC);
+ llvm::DenseSet<const CFGBlock *> Visited;
Worklist.enqueueBlock(&VarBlk);
while (const CFGBlock *B = Worklist.dequeue()) {
+ if (Visited.contains(B))
+ continue;
+ Visited.insert(B);
// First check the current block.
for (CFGBlock::const_reverse_iterator ri = B->rbegin(), re = B->rend();
ri != re; ++ri) {
diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index fbfb242..1f040c8 100644
--- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -20,26 +20,19 @@ char MultiplexExternalSemaSource::ID;
/// given element to it.
///
MultiplexExternalSemaSource::MultiplexExternalSemaSource(
- ExternalSemaSource *S1, ExternalSemaSource *S2) {
- S1->Retain();
- S2->Retain();
- Sources.push_back(S1);
- Sources.push_back(S2);
-}
-
-// pin the vtable here.
-MultiplexExternalSemaSource::~MultiplexExternalSemaSource() {
- for (auto *S : Sources)
- S->Release();
+ llvm::IntrusiveRefCntPtr<ExternalSemaSource> S1,
+ llvm::IntrusiveRefCntPtr<ExternalSemaSource> S2) {
+ Sources.push_back(std::move(S1));
+ Sources.push_back(std::move(S2));
}
/// Appends new source to the source list.
///
///\param[in] source - An ExternalSemaSource.
///
-void MultiplexExternalSemaSource::AddSource(ExternalSemaSource *Source) {
- Source->Retain();
- Sources.push_back(Source);
+void MultiplexExternalSemaSource::AddSource(
+ llvm::IntrusiveRefCntPtr<ExternalSemaSource> Source) {
+ Sources.push_back(std::move(Source));
}
//===----------------------------------------------------------------------===//
@@ -92,7 +85,7 @@ CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers(
CXXCtorInitializer **
MultiplexExternalSemaSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
- for (auto *S : Sources)
+ for (auto &S : Sources)
if (auto *R = S->GetExternalCXXCtorInitializers(Offset))
return R;
return nullptr;
@@ -371,6 +364,6 @@ bool MultiplexExternalSemaSource::MaybeDiagnoseMissingCompleteType(
void MultiplexExternalSemaSource::AssignedLambdaNumbering(
CXXRecordDecl *Lambda) {
- for (auto *Source : Sources)
+ for (auto &Source : Sources)
Source->AssignedLambdaNumbering(Lambda);
}
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index d50eeff..924becf 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -656,18 +656,19 @@ ASTMutationListener *Sema::getASTMutationListener() const {
return getASTConsumer().GetASTMutationListener();
}
-void Sema::addExternalSource(ExternalSemaSource *E) {
+void Sema::addExternalSource(IntrusiveRefCntPtr<ExternalSemaSource> E) {
assert(E && "Cannot use with NULL ptr");
if (!ExternalSource) {
- ExternalSource = E;
+ ExternalSource = std::move(E);
return;
}
- if (auto *Ex = dyn_cast<MultiplexExternalSemaSource>(ExternalSource))
- Ex->AddSource(E);
+ if (auto *Ex = dyn_cast<MultiplexExternalSemaSource>(ExternalSource.get()))
+ Ex->AddSource(std::move(E));
else
- ExternalSource = new MultiplexExternalSemaSource(ExternalSource.get(), E);
+ ExternalSource = llvm::makeIntrusiveRefCnt<MultiplexExternalSemaSource>(
+ ExternalSource, std::move(E));
}
void Sema::PrintStats() const {
@@ -2251,16 +2252,15 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
}
// Don't allow SVE types in functions without a SVE target.
- if (Ty->isSVESizelessBuiltinType() && FD) {
+ if (Ty->isSVESizelessBuiltinType() && FD && !FD->getType().isNull()) {
llvm::StringMap<bool> CallerFeatureMap;
Context.getFunctionFeatureMap(CallerFeatureMap, FD);
if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap)) {
if (!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap))
Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty;
else if (!IsArmStreamingFunction(FD,
- /*IncludeLocallyStreaming=*/true)) {
+ /*IncludeLocallyStreaming=*/true))
Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;
- }
}
}
diff --git a/clang/lib/Sema/SemaAMDGPU.cpp b/clang/lib/Sema/SemaAMDGPU.cpp
index c23c98a..a5fbd70 100644
--- a/clang/lib/Sema/SemaAMDGPU.cpp
+++ b/clang/lib/Sema/SemaAMDGPU.cpp
@@ -84,6 +84,22 @@ bool SemaAMDGPU::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
return checkMovDPPFunctionCall(TheCall, 2, 1);
case AMDGPU::BI__builtin_amdgcn_update_dpp: {
return checkMovDPPFunctionCall(TheCall, 6, 2);
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_fp8:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_fp8:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_bf8:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_bf8:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_fp4:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_fp4:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_fp8:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_bf8:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_fp4:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f16_fp6:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_bf16_fp6:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f16_bf6:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_bf16_bf6:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f32_fp6:
+ case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f32_bf6:
+ return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);
}
default:
return false;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index c74b671..bc87611 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -15893,9 +15893,7 @@ ExprResult Sema::BuiltinMatrixTranspose(CallExpr *TheCall,
// Get and verify the matrix dimensions.
static std::optional<unsigned>
getAndVerifyMatrixDimension(Expr *Expr, StringRef Name, Sema &S) {
- SourceLocation ErrorPos;
- std::optional<llvm::APSInt> Value =
- Expr->getIntegerConstantExpr(S.Context, &ErrorPos);
+ std::optional<llvm::APSInt> Value = Expr->getIntegerConstantExpr(S.Context);
if (!Value) {
S.Diag(Expr->getBeginLoc(), diag::err_builtin_matrix_scalar_unsigned_arg)
<< Name;
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index a43ac9e..0de5580 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -4034,6 +4034,14 @@ static void AddOverloadParameterChunks(
return;
}
+ // C++23 introduces an explicit object parameter, a.k.a. "deducing this"
+ // Skip it for autocomplete and treat the next parameter as the first
+ // parameter
+ if (Function && FirstParameter &&
+ Function->getParamDecl(P)->isExplicitObjectParameter()) {
+ continue;
+ }
+
if (FirstParameter)
FirstParameter = false;
else
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c7e7507..e2ac648 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3063,7 +3063,8 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
// error since the definition will have already been created without
// the semantic effects of the attribute having been applied.
S.Diag(NewAttribute->getLocation(),
- diag::err_sycl_entry_point_after_definition);
+ diag::err_sycl_entry_point_after_definition)
+ << NewAttribute;
S.Diag(Def->getLocation(), diag::note_previous_definition);
cast<SYCLKernelEntryPointAttr>(NewAttribute)->setInvalidAttr();
++I;
@@ -14723,9 +14724,9 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
type->isIntegralOrEnumerationType()) {
// In C++98, in-class initialization for a static data member must
// be an integer constant expression.
- SourceLocation Loc;
- if (!Init->isIntegerConstantExpr(Context, &Loc)) {
- Diag(Loc, diag::ext_in_class_initializer_non_constant)
+ if (!Init->isIntegerConstantExpr(Context)) {
+ Diag(Init->getExprLoc(),
+ diag::ext_in_class_initializer_non_constant)
<< Init->getSourceRange();
}
}
@@ -16258,19 +16259,19 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
FD->getAttr<SYCLKernelEntryPointAttr>();
if (FD->isDefaulted()) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*defaulted function*/ 3;
+ << SKEPAttr << /*defaulted function*/ 3;
SKEPAttr->setInvalidAttr();
} else if (FD->isDeleted()) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*deleted function*/ 2;
+ << SKEPAttr << /*deleted function*/ 2;
SKEPAttr->setInvalidAttr();
} else if (FSI->isCoroutine()) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*coroutine*/ 7;
+ << SKEPAttr << /*coroutine*/ 7;
SKEPAttr->setInvalidAttr();
} else if (Body && isa<CXXTryStmt>(Body)) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*function defined with a function try block*/ 8;
+ << SKEPAttr << /*function defined with a function try block*/ 8;
SKEPAttr->setInvalidAttr();
}
diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp
index 3e03cb4..4683c81 100644
--- a/clang/lib/Sema/SemaSYCL.cpp
+++ b/clang/lib/Sema/SemaSYCL.cpp
@@ -262,12 +262,13 @@ void SemaSYCL::CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD) {
if (!getASTContext().hasSameType(SAI->getKernelName(),
SKEPAttr->getKernelName())) {
Diag(SAI->getLocation(), diag::err_sycl_entry_point_invalid_redeclaration)
- << SAI->getKernelName() << SKEPAttr->getKernelName();
+ << SKEPAttr << SAI->getKernelName() << SKEPAttr->getKernelName();
Diag(SKEPAttr->getLocation(), diag::note_previous_attribute);
SAI->setInvalidAttr();
} else {
Diag(SAI->getLocation(),
- diag::warn_sycl_entry_point_redundant_declaration);
+ diag::warn_sycl_entry_point_redundant_declaration)
+ << SAI;
Diag(SKEPAttr->getLocation(), diag::note_previous_attribute);
}
}
@@ -289,7 +290,8 @@ void SemaSYCL::CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD) {
PrevSKEPAttr->getKernelName())) {
Diag(SKEPAttr->getLocation(),
diag::err_sycl_entry_point_invalid_redeclaration)
- << SKEPAttr->getKernelName() << PrevSKEPAttr->getKernelName();
+ << SKEPAttr << SKEPAttr->getKernelName()
+ << PrevSKEPAttr->getKernelName();
Diag(PrevSKEPAttr->getLocation(), diag::note_previous_decl) << PrevFD;
SKEPAttr->setInvalidAttr();
}
@@ -299,50 +301,52 @@ void SemaSYCL::CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD) {
if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (!MD->isStatic()) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*non-static member function*/ 0;
+ << SKEPAttr << /*non-static member function*/ 0;
SKEPAttr->setInvalidAttr();
}
}
if (FD->isVariadic()) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*variadic function*/ 1;
+ << SKEPAttr << /*variadic function*/ 1;
SKEPAttr->setInvalidAttr();
}
if (FD->isDefaulted()) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*defaulted function*/ 3;
+ << SKEPAttr << /*defaulted function*/ 3;
SKEPAttr->setInvalidAttr();
} else if (FD->isDeleted()) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*deleted function*/ 2;
+ << SKEPAttr << /*deleted function*/ 2;
SKEPAttr->setInvalidAttr();
}
if (FD->isConsteval()) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*consteval function*/ 5;
+ << SKEPAttr << /*consteval function*/ 5;
SKEPAttr->setInvalidAttr();
} else if (FD->isConstexpr()) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*constexpr function*/ 4;
+ << SKEPAttr << /*constexpr function*/ 4;
SKEPAttr->setInvalidAttr();
}
if (FD->isNoReturn()) {
Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
- << /*function declared with the 'noreturn' attribute*/ 6;
+ << SKEPAttr << /*function declared with the 'noreturn' attribute*/ 6;
SKEPAttr->setInvalidAttr();
}
if (FD->getReturnType()->isUndeducedType()) {
Diag(SKEPAttr->getLocation(),
- diag::err_sycl_entry_point_deduced_return_type);
+ diag::err_sycl_entry_point_deduced_return_type)
+ << SKEPAttr;
SKEPAttr->setInvalidAttr();
} else if (!FD->getReturnType()->isDependentType() &&
!FD->getReturnType()->isVoidType()) {
- Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_return_type);
+ Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_return_type)
+ << SKEPAttr;
SKEPAttr->setInvalidAttr();
}
@@ -354,7 +358,8 @@ void SemaSYCL::CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD) {
if (!declaresSameEntity(FD, SKI->getKernelEntryPointDecl())) {
// FIXME: This diagnostic should include the origin of the kernel
// FIXME: names; not just the locations of the conflicting declarations.
- Diag(FD->getLocation(), diag::err_sycl_kernel_name_conflict);
+ Diag(FD->getLocation(), diag::err_sycl_kernel_name_conflict)
+ << SKEPAttr;
Diag(SKI->getKernelEntryPointDecl()->getLocation(),
diag::note_previous_declaration);
SKEPAttr->setInvalidAttr();
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 572dbf2..b0a673d 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -1387,7 +1387,8 @@ static void CheckFoldOperand(Sema &S, Expr *E) {
S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand)
<< E->getSourceRange()
<< FixItHint::CreateInsertion(E->getBeginLoc(), "(")
- << FixItHint::CreateInsertion(E->getEndLoc(), ")");
+ << FixItHint::CreateInsertion(S.getLocForEndOfToken(E->getEndLoc()),
+ ")");
}
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f896f9f1..682d263 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -677,8 +677,7 @@ bool PCHValidator::ReadDiagnosticOptions(DiagnosticOptions &DiagOpts,
bool Complain) {
DiagnosticsEngine &ExistingDiags = PP.getDiagnostics();
IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(ExistingDiags.getDiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagIDs, DiagOpts));
+ auto Diags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(DiagIDs, DiagOpts);
// This should never fail, because we would have processed these options
// before writing them to an ASTFile.
ProcessWarningOptions(*Diags, DiagOpts,
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index bd84a97..cdaf38d 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1147,7 +1147,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
const SYCLKernelInfo *SKI = C.findSYCLKernelInfo(SKEPAttr->getKernelName());
if (SKI) {
if (!declaresSameEntity(FD, SKI->getKernelEntryPointDecl())) {
- Reader.Diag(FD->getLocation(), diag::err_sycl_kernel_name_conflict);
+ Reader.Diag(FD->getLocation(), diag::err_sycl_kernel_name_conflict)
+ << SKEPAttr;
Reader.Diag(SKI->getKernelEntryPointDecl()->getLocation(),
diag::note_previous_declaration);
SKEPAttr->setInvalidAttr();
diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 88feb6a..e682c4e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -99,7 +99,7 @@ class NilArgChecker : public Checker<check::PreObjCMessage,
check::PostStmt<ObjCDictionaryLiteral>,
check::PostStmt<ObjCArrayLiteral>,
EventDispatcher<ImplicitNullDerefEvent>> {
- mutable std::unique_ptr<APIMisuse> BT;
+ const APIMisuse BT{this, "nil argument"};
mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors;
mutable Selector ArrayWithObjectSel;
@@ -218,10 +218,7 @@ void NilArgChecker::generateBugReport(ExplodedNode *N,
SourceRange Range,
const Expr *E,
CheckerContext &C) const {
- if (!BT)
- BT.reset(new APIMisuse(this, "nil argument"));
-
- auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
+ auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
R->addRange(Range);
bugreporter::trackExpressionValue(N, E, *R);
C.emitReport(std::move(R));
@@ -350,7 +347,7 @@ void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
namespace {
class CFNumberChecker : public Checker< check::PreStmt<CallExpr> > {
- mutable std::unique_ptr<APIMisuse> BT;
+ const APIMisuse BT{this, "Bad use of CFNumber APIs"};
mutable IdentifierInfo *ICreate = nullptr, *IGetValue = nullptr;
public:
CFNumberChecker() = default;
@@ -524,10 +521,7 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE,
<< " bits of the integer value will be "
<< (isCreate ? "lost." : "garbage.");
- if (!BT)
- BT.reset(new APIMisuse(this, "Bad use of CFNumber APIs"));
-
- auto report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
+ auto report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
report->addRange(CE->getArg(2)->getSourceRange());
C.emitReport(std::move(report));
}
@@ -539,7 +533,7 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE,
namespace {
class CFRetainReleaseChecker : public Checker<check::PreCall> {
- mutable APIMisuse BT{this, "null passed to CF memory management function"};
+ const APIMisuse BT{this, "null passed to CF memory management function"};
const CallDescriptionSet ModelledCalls = {
{CDM::CLibrary, {"CFRetain"}, 1},
{CDM::CLibrary, {"CFRelease"}, 1},
@@ -600,7 +594,8 @@ class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
mutable Selector retainS;
mutable Selector autoreleaseS;
mutable Selector drainS;
- mutable std::unique_ptr<BugType> BT;
+ const APIMisuse BT{
+ this, "message incorrectly sent to class instead of class instance"};
public:
void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
@@ -609,10 +604,7 @@ public:
void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const {
- if (!BT) {
- BT.reset(new APIMisuse(
- this, "message incorrectly sent to class instead of class instance"));
-
+ if (releaseS.isNull()) {
ASTContext &Ctx = C.getASTContext();
releaseS = GetNullarySelector("release", Ctx);
retainS = GetNullarySelector("retain", Ctx);
@@ -639,7 +631,7 @@ void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
"of class '" << Class->getName()
<< "' and not the class directly";
- auto report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
+ auto report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
report->addRange(msg.getSourceRange());
C.emitReport(std::move(report));
}
@@ -658,7 +650,8 @@ class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
mutable Selector orderedSetWithObjectsS;
mutable Selector initWithObjectsS;
mutable Selector initWithObjectsAndKeysS;
- mutable std::unique_ptr<BugType> BT;
+ const APIMisuse BT{this, "Arguments passed to variadic method aren't all "
+ "Objective-C pointer types"};
bool isVariadicMessage(const ObjCMethodCall &msg) const;
@@ -717,11 +710,7 @@ VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const {
- if (!BT) {
- BT.reset(new APIMisuse(this,
- "Arguments passed to variadic method aren't all "
- "Objective-C pointer types"));
-
+ if (arrayWithObjectsS.isNull()) {
ASTContext &Ctx = C.getASTContext();
arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
dictionaryWithObjectsAndKeysS =
@@ -792,8 +781,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
ArgTy.print(os, C.getLangOpts());
os << "'";
- auto R =
- std::make_unique<PathSensitiveBugReport>(*BT, os.str(), *errorNode);
+ auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), *errorNode);
R->addRange(msg.getArgSourceRange(I));
C.emitReport(std::move(R));
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 31cb150..fd0a398 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -78,35 +78,30 @@ static QualType getCharPtrType(ASTContext &Ctx, CharKind CK) {
: Ctx.WideCharTy);
}
-class CStringChecker : public Checker< eval::Call,
- check::PreStmt<DeclStmt>,
- check::LiveSymbols,
- check::DeadSymbols,
- check::RegionChanges
- > {
- mutable std::unique_ptr<BugType> BT_Null, BT_Bounds, BT_Overlap,
- BT_NotCString, BT_AdditionOverflow, BT_UninitRead;
-
+class CStringChecker
+ : public CheckerFamily<eval::Call, check::PreStmt<DeclStmt>,
+ check::LiveSymbols, check::DeadSymbols,
+ check::RegionChanges> {
mutable const char *CurrentFunctionDescription = nullptr;
public:
- /// The filter is used to filter out the diagnostics which are not enabled by
- /// the user.
- struct CStringChecksFilter {
- bool CheckCStringNullArg = false;
- bool CheckCStringOutOfBounds = false;
- bool CheckCStringBufferOverlap = false;
- bool CheckCStringNotNullTerm = false;
- bool CheckCStringUninitializedRead = false;
-
- CheckerNameRef CheckNameCStringNullArg;
- CheckerNameRef CheckNameCStringOutOfBounds;
- CheckerNameRef CheckNameCStringBufferOverlap;
- CheckerNameRef CheckNameCStringNotNullTerm;
- CheckerNameRef CheckNameCStringUninitializedRead;
- };
-
- CStringChecksFilter Filter;
+ // FIXME: The bug types emitted by this checker family have confused garbage
+ // in their Description and Category fields (e.g. `categories::UnixAPI` is
+ // passed as the description in several cases and `uninitialized` is mistyped
+ // as `unitialized`). This should be cleaned up.
+ CheckerFrontendWithBugType NullArg{categories::UnixAPI};
+ CheckerFrontendWithBugType OutOfBounds{"Out-of-bound array access"};
+ CheckerFrontendWithBugType BufferOverlap{categories::UnixAPI,
+ "Improper arguments"};
+ CheckerFrontendWithBugType NotNullTerm{categories::UnixAPI};
+ CheckerFrontendWithBugType UninitializedRead{
+ "Accessing unitialized/garbage values"};
+
+ // FIXME: This bug type should be removed because it is only emitted in a
+ // situation that is practically impossible.
+ const BugType AdditionOverflow{&OutOfBounds, "API"};
+
+ StringRef getDebugTag() const override { return "MallocChecker"; }
static void *getTag() { static int tag; return &tag; }
@@ -384,7 +379,7 @@ ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C,
assumeZero(C, State, l, Arg.Expression->getType());
if (stateNull && !stateNonNull) {
- if (Filter.CheckCStringNullArg) {
+ if (NullArg.isEnabled()) {
SmallString<80> buf;
llvm::raw_svector_ostream OS(buf);
assert(CurrentFunctionDescription);
@@ -468,7 +463,7 @@ ProgramStateRef CStringChecker::checkInit(CheckerContext &C,
return State;
// Ensure that we wouldn't read uninitialized value.
- if (Filter.CheckCStringUninitializedRead &&
+ if (UninitializedRead.isEnabled() &&
State->getSVal(*FirstElementVal).isUndef()) {
llvm::SmallString<258> Buf;
llvm::raw_svector_ostream OS(Buf);
@@ -524,7 +519,7 @@ ProgramStateRef CStringChecker::checkInit(CheckerContext &C,
if (!isa<Loc>(LastElementVal))
return State;
- if (Filter.CheckCStringUninitializedRead &&
+ if (UninitializedRead.isEnabled() &&
State->getSVal(LastElementVal.castAs<Loc>()).isUndef()) {
const llvm::APSInt *IdxInt = LastIdx.getAsInteger();
// If we can't get emit a sensible last element index, just bail out --
@@ -581,13 +576,9 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
auto [StInBound, StOutBound] = state->assumeInBoundDual(*Idx, Size);
if (StOutBound && !StInBound) {
- // These checks are either enabled by the CString out-of-bounds checker
- // explicitly or implicitly by the Malloc checker.
- // In the latter case we only do modeling but do not emit warning.
- if (!Filter.CheckCStringOutOfBounds)
+ if (!OutOfBounds.isEnabled())
return nullptr;
- // Emit a bug report.
ErrorMessage Message =
createOutOfBoundErrorMsg(CurrentFunctionDescription, Access);
emitOutOfBoundsBug(C, StOutBound, Buffer.Expression, Message);
@@ -620,7 +611,7 @@ CStringChecker::CheckBufferAccess(CheckerContext &C, ProgramStateRef State,
return nullptr;
// If out-of-bounds checking is turned off, skip the rest.
- if (!Filter.CheckCStringOutOfBounds)
+ if (!OutOfBounds.isEnabled())
return State;
SVal BufStart =
@@ -670,7 +661,7 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
SizeArgExpr Size, AnyArgExpr First,
AnyArgExpr Second,
CharKind CK) const {
- if (!Filter.CheckCStringBufferOverlap)
+ if (!BufferOverlap.isEnabled())
return state;
// Do a simple check for overlap: if the two arguments are from the same
@@ -789,13 +780,9 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
if (!N)
return;
- if (!BT_Overlap)
- BT_Overlap.reset(new BugType(Filter.CheckNameCStringBufferOverlap,
- categories::UnixAPI, "Improper arguments"));
-
// Generate a report for this bug.
auto report = std::make_unique<PathSensitiveBugReport>(
- *BT_Overlap, "Arguments must not be overlapping buffers", N);
+ BufferOverlap, "Arguments must not be overlapping buffers", N);
report->addRange(First->getSourceRange());
report->addRange(Second->getSourceRange());
@@ -805,15 +792,8 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
void CStringChecker::emitNullArgBug(CheckerContext &C, ProgramStateRef State,
const Stmt *S, StringRef WarningMsg) const {
if (ExplodedNode *N = C.generateErrorNode(State)) {
- if (!BT_Null) {
- // FIXME: This call uses the string constant 'categories::UnixAPI' as the
- // description of the bug; it should be replaced by a real description.
- BT_Null.reset(
- new BugType(Filter.CheckNameCStringNullArg, categories::UnixAPI));
- }
-
auto Report =
- std::make_unique<PathSensitiveBugReport>(*BT_Null, WarningMsg, N);
+ std::make_unique<PathSensitiveBugReport>(NullArg, WarningMsg, N);
Report->addRange(S->getSourceRange());
if (const auto *Ex = dyn_cast<Expr>(S))
bugreporter::trackExpressionValue(N, Ex, *Report);
@@ -826,12 +806,8 @@ void CStringChecker::emitUninitializedReadBug(CheckerContext &C,
const Expr *E, const MemRegion *R,
StringRef Msg) const {
if (ExplodedNode *N = C.generateErrorNode(State)) {
- if (!BT_UninitRead)
- BT_UninitRead.reset(new BugType(Filter.CheckNameCStringUninitializedRead,
- "Accessing unitialized/garbage values"));
-
auto Report =
- std::make_unique<PathSensitiveBugReport>(*BT_UninitRead, Msg, N);
+ std::make_unique<PathSensitiveBugReport>(UninitializedRead, Msg, N);
Report->addNote("Other elements might also be undefined",
Report->getLocation());
Report->addRange(E->getSourceRange());
@@ -845,17 +821,11 @@ void CStringChecker::emitOutOfBoundsBug(CheckerContext &C,
ProgramStateRef State, const Stmt *S,
StringRef WarningMsg) const {
if (ExplodedNode *N = C.generateErrorNode(State)) {
- if (!BT_Bounds)
- BT_Bounds.reset(new BugType(Filter.CheckCStringOutOfBounds
- ? Filter.CheckNameCStringOutOfBounds
- : Filter.CheckNameCStringNullArg,
- "Out-of-bound array access"));
-
// FIXME: It would be nice to eventually make this diagnostic more clear,
// e.g., by referencing the original declaration or by saying *why* this
// reference is outside the range.
auto Report =
- std::make_unique<PathSensitiveBugReport>(*BT_Bounds, WarningMsg, N);
+ std::make_unique<PathSensitiveBugReport>(OutOfBounds, WarningMsg, N);
Report->addRange(S->getSourceRange());
C.emitReport(std::move(Report));
}
@@ -865,15 +835,8 @@ void CStringChecker::emitNotCStringBug(CheckerContext &C, ProgramStateRef State,
const Stmt *S,
StringRef WarningMsg) const {
if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) {
- if (!BT_NotCString) {
- // FIXME: This call uses the string constant 'categories::UnixAPI' as the
- // description of the bug; it should be replaced by a real description.
- BT_NotCString.reset(
- new BugType(Filter.CheckNameCStringNotNullTerm, categories::UnixAPI));
- }
-
auto Report =
- std::make_unique<PathSensitiveBugReport>(*BT_NotCString, WarningMsg, N);
+ std::make_unique<PathSensitiveBugReport>(NotNullTerm, WarningMsg, N);
Report->addRange(S->getSourceRange());
C.emitReport(std::move(Report));
@@ -883,14 +846,6 @@ void CStringChecker::emitNotCStringBug(CheckerContext &C, ProgramStateRef State,
void CStringChecker::emitAdditionOverflowBug(CheckerContext &C,
ProgramStateRef State) const {
if (ExplodedNode *N = C.generateErrorNode(State)) {
- if (!BT_AdditionOverflow) {
- // FIXME: This call uses the word "API" as the description of the bug;
- // it should be replaced by a better error message (if this unlikely
- // situation continues to exist as a separate bug type).
- BT_AdditionOverflow.reset(
- new BugType(Filter.CheckNameCStringOutOfBounds, "API"));
- }
-
// This isn't a great error message, but this should never occur in real
// code anyway -- you'd have to create a buffer longer than a size_t can
// represent, which is sort of a contradiction.
@@ -898,7 +853,7 @@ void CStringChecker::emitAdditionOverflowBug(CheckerContext &C,
"This expression will create a string whose length is too big to "
"be represented as a size_t";
- auto Report = std::make_unique<PathSensitiveBugReport>(*BT_AdditionOverflow,
+ auto Report = std::make_unique<PathSensitiveBugReport>(AdditionOverflow,
WarningMsg, N);
C.emitReport(std::move(Report));
}
@@ -909,7 +864,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
NonLoc left,
NonLoc right) const {
// If out-of-bounds checking is turned off, skip the rest.
- if (!Filter.CheckCStringOutOfBounds)
+ if (!OutOfBounds.isEnabled())
return state;
// If a previous check has failed, propagate the failure.
@@ -1048,7 +1003,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
// C string. In the context of locations, the only time we can issue such
// a warning is for labels.
if (std::optional<loc::GotoLabel> Label = Buf.getAs<loc::GotoLabel>()) {
- if (Filter.CheckCStringNotNullTerm) {
+ if (NotNullTerm.isEnabled()) {
SmallString<120> buf;
llvm::raw_svector_ostream os(buf);
assert(CurrentFunctionDescription);
@@ -1110,7 +1065,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
// Other regions (mostly non-data) can't have a reliable C string length.
// In this case, an error is emitted and UndefinedVal is returned.
// The caller should always be prepared to handle this case.
- if (Filter.CheckCStringNotNullTerm) {
+ if (NotNullTerm.isEnabled()) {
SmallString<120> buf;
llvm::raw_svector_ostream os(buf);
@@ -2873,24 +2828,27 @@ void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
}
void ento::registerCStringModeling(CheckerManager &Mgr) {
- Mgr.registerChecker<CStringChecker>();
+ // Other checker relies on the modeling implemented in this checker family,
+ // so this "modeling checker" can register the 'CStringChecker' backend for
+ // its callbacks without enabling any of its frontends.
+ Mgr.getChecker<CStringChecker>();
}
-bool ento::shouldRegisterCStringModeling(const CheckerManager &mgr) {
+bool ento::shouldRegisterCStringModeling(const CheckerManager &) {
return true;
}
-#define REGISTER_CHECKER(name) \
- void ento::register##name(CheckerManager &mgr) { \
- CStringChecker *checker = mgr.getChecker<CStringChecker>(); \
- checker->Filter.Check##name = true; \
- checker->Filter.CheckName##name = mgr.getCurrentCheckerName(); \
+#define REGISTER_CHECKER(NAME) \
+ void ento::registerCString##NAME(CheckerManager &Mgr) { \
+ Mgr.getChecker<CStringChecker>()->NAME.enable(Mgr); \
} \
\
- bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
+ bool ento::shouldRegisterCString##NAME(const CheckerManager &) { \
+ return true; \
+ }
-REGISTER_CHECKER(CStringNullArg)
-REGISTER_CHECKER(CStringOutOfBounds)
-REGISTER_CHECKER(CStringBufferOverlap)
-REGISTER_CHECKER(CStringNotNullTerm)
-REGISTER_CHECKER(CStringUninitializedRead)
+REGISTER_CHECKER(NullArg)
+REGISTER_CHECKER(OutOfBounds)
+REGISTER_CHECKER(BufferOverlap)
+REGISTER_CHECKER(NotNullTerm)
+REGISTER_CHECKER(UninitializedRead)
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
index 839c8bc..a227ca0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
@@ -111,32 +111,12 @@ bool PlacementNewChecker::checkPlaceCapacityIsSufficient(
if (!SizeOfPlaceCI)
return true;
- if ((SizeOfPlaceCI->getValue() < SizeOfTargetCI->getValue()) ||
- (IsArrayTypeAllocated &&
- SizeOfPlaceCI->getValue() >= SizeOfTargetCI->getValue())) {
+ if ((SizeOfPlaceCI->getValue() < SizeOfTargetCI->getValue())) {
if (ExplodedNode *N = C.generateErrorNode(C.getState())) {
- std::string Msg;
- // TODO: use clang constant
- if (IsArrayTypeAllocated &&
- SizeOfPlaceCI->getValue() > SizeOfTargetCI->getValue())
- Msg = std::string(llvm::formatv(
- "{0} bytes is possibly not enough for array allocation which "
- "requires {1} bytes. Current overhead requires the size of {2} "
- "bytes",
- SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue(),
- *SizeOfPlaceCI->getValue() - SizeOfTargetCI->getValue()));
- else if (IsArrayTypeAllocated &&
- SizeOfPlaceCI->getValue() == SizeOfTargetCI->getValue())
- Msg = std::string(llvm::formatv(
- "Storage provided to placement new is only {0} bytes, "
- "whereas the allocated array type requires more space for "
- "internal needs",
- SizeOfPlaceCI->getValue()));
- else
- Msg = std::string(llvm::formatv(
- "Storage provided to placement new is only {0} bytes, "
- "whereas the allocated type requires {1} bytes",
- SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue()));
+ std::string Msg =
+ llvm::formatv("Storage provided to placement new is only {0} bytes, "
+ "whereas the allocated type requires {1} bytes",
+ SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue());
auto R = std::make_unique<PathSensitiveBugReport>(SBT, Msg, N);
bugreporter::trackExpressionValue(N, NE->getPlacementArg(0), *R);
diff --git a/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
index 15fd9a0..d2760ca 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
@@ -142,34 +142,19 @@ void CFErrorFunctionChecker::checkASTDecl(const FunctionDecl *D,
//===----------------------------------------------------------------------===//
namespace {
+class NSOrCFErrorDerefChecker
+ : public CheckerFamily<check::Location,
+ check::Event<ImplicitNullDerefEvent>> {
+ mutable IdentifierInfo *NSErrorII = nullptr;
+ mutable IdentifierInfo *CFErrorII = nullptr;
-class NSErrorDerefBug : public BugType {
-public:
- NSErrorDerefBug(const CheckerNameRef Checker)
- : BugType(Checker, "NSError** null dereference",
- "Coding conventions (Apple)") {}
-};
-
-class CFErrorDerefBug : public BugType {
public:
- CFErrorDerefBug(const CheckerNameRef Checker)
- : BugType(Checker, "CFErrorRef* null dereference",
- "Coding conventions (Apple)") {}
-};
-
-}
+ CheckerFrontendWithBugType NSError{"NSError** null dereference",
+ "Coding conventions (Apple)"};
+ CheckerFrontendWithBugType CFError{"CFErrorRef* null dereference",
+ "Coding conventions (Apple)"};
-namespace {
-class NSOrCFErrorDerefChecker
- : public Checker< check::Location,
- check::Event<ImplicitNullDerefEvent> > {
- mutable IdentifierInfo *NSErrorII, *CFErrorII;
- mutable std::unique_ptr<NSErrorDerefBug> NSBT;
- mutable std::unique_ptr<CFErrorDerefBug> CFBT;
-public:
- bool ShouldCheckNSError = false, ShouldCheckCFError = false;
- CheckerNameRef NSErrorName, CFErrorName;
- NSOrCFErrorDerefChecker() : NSErrorII(nullptr), CFErrorII(nullptr) {}
+ StringRef getDebugTag() const override { return "NSOrCFErrorDerefChecker"; }
void checkLocation(SVal loc, bool isLoad, const Stmt *S,
CheckerContext &C) const;
@@ -236,12 +221,12 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad,
if (!CFErrorII)
CFErrorII = &Ctx.Idents.get("CFErrorRef");
- if (ShouldCheckNSError && IsNSError(parmT, NSErrorII)) {
+ if (NSError.isEnabled() && IsNSError(parmT, NSErrorII)) {
setFlag<NSErrorOut>(state, state->getSVal(loc.castAs<Loc>()), C);
return;
}
- if (ShouldCheckCFError && IsCFError(parmT, CFErrorII)) {
+ if (CFError.isEnabled() && IsCFError(parmT, CFErrorII)) {
setFlag<CFErrorOut>(state, state->getSVal(loc.castAs<Loc>()), C);
return;
}
@@ -274,19 +259,9 @@ void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const {
os << " may be null";
- BugType *bug = nullptr;
- if (isNSError) {
- if (!NSBT)
- NSBT.reset(new NSErrorDerefBug(NSErrorName));
- bug = NSBT.get();
- }
- else {
- if (!CFBT)
- CFBT.reset(new CFErrorDerefBug(CFErrorName));
- bug = CFBT.get();
- }
+ const BugType &BT = isNSError ? NSError : CFError;
BR.emitReport(
- std::make_unique<PathSensitiveBugReport>(*bug, os.str(), event.SinkNode));
+ std::make_unique<PathSensitiveBugReport>(BT, os.str(), event.SinkNode));
}
static bool IsNSError(QualType T, IdentifierInfo *II) {
@@ -320,32 +295,21 @@ static bool IsCFError(QualType T, IdentifierInfo *II) {
return TT->getDecl()->getIdentifier() == II;
}
-void ento::registerNSOrCFErrorDerefChecker(CheckerManager &mgr) {
- mgr.registerChecker<NSOrCFErrorDerefChecker>();
-}
-
-bool ento::shouldRegisterNSOrCFErrorDerefChecker(const CheckerManager &mgr) {
- return true;
-}
-
-void ento::registerNSErrorChecker(CheckerManager &mgr) {
- mgr.registerChecker<NSErrorMethodChecker>();
- NSOrCFErrorDerefChecker *checker = mgr.getChecker<NSOrCFErrorDerefChecker>();
- checker->ShouldCheckNSError = true;
- checker->NSErrorName = mgr.getCurrentCheckerName();
-}
-
-bool ento::shouldRegisterNSErrorChecker(const CheckerManager &mgr) {
- return true;
-}
-
-void ento::registerCFErrorChecker(CheckerManager &mgr) {
- mgr.registerChecker<CFErrorFunctionChecker>();
- NSOrCFErrorDerefChecker *checker = mgr.getChecker<NSOrCFErrorDerefChecker>();
- checker->ShouldCheckCFError = true;
- checker->CFErrorName = mgr.getCurrentCheckerName();
-}
+// This source file implements two user-facing checkers ("osx.cocoa.NSError"
+// and "osx.coreFoundation.CFError") which are both implemented as the
+// combination of two `CheckerFrontend`s that are registered under the same
+// name (but otherwise act independently). Among these 2+2 `CheckerFrontend`s
+// two are coming from the checker family `NSOrCFErrorDerefChecker` while the
+// other two (the `ADDITIONAL_PART`s) are small standalone checkers.
+#define REGISTER_CHECKER(NAME, ADDITIONAL_PART) \
+ void ento::register##NAME##Checker(CheckerManager &Mgr) { \
+ Mgr.getChecker<NSOrCFErrorDerefChecker>()->NAME.enable(Mgr); \
+ Mgr.registerChecker<ADDITIONAL_PART>(); \
+ } \
+ \
+ bool ento::shouldRegister##NAME##Checker(const CheckerManager &) { \
+ return true; \
+ }
-bool ento::shouldRegisterCFErrorChecker(const CheckerManager &mgr) {
- return true;
-}
+REGISTER_CHECKER(NSError, NSErrorMethodChecker)
+REGISTER_CHECKER(CFError, CFErrorFunctionChecker)
diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index a63497c..019e81f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -28,23 +28,22 @@ using namespace ento;
namespace {
class StackAddrEscapeChecker
- : public Checker<check::PreCall, check::PreStmt<ReturnStmt>,
- check::EndFunction> {
+ : public CheckerFamily<check::PreCall, check::PreStmt<ReturnStmt>,
+ check::EndFunction> {
mutable IdentifierInfo *dispatch_semaphore_tII = nullptr;
- mutable std::unique_ptr<BugType> BT_stackleak;
- mutable std::unique_ptr<BugType> BT_returnstack;
- mutable std::unique_ptr<BugType> BT_capturedstackasync;
- mutable std::unique_ptr<BugType> BT_capturedstackret;
public:
- enum CheckKind {
- CK_StackAddrEscapeChecker,
- CK_StackAddrAsyncEscapeChecker,
- CK_NumCheckKinds
- };
+ StringRef getDebugTag() const override { return "StackAddrEscapeChecker"; }
+
+ CheckerFrontend StackAddrEscape;
+ CheckerFrontend StackAddrAsyncEscape;
- bool ChecksEnabled[CK_NumCheckKinds] = {false};
- CheckerNameRef CheckNames[CK_NumCheckKinds];
+ const BugType StackLeak{&StackAddrEscape,
+ "Stack address leaks outside of stack frame"};
+ const BugType ReturnStack{&StackAddrEscape,
+ "Return of address to stack-allocated memory"};
+ const BugType CapturedStackAsync{
+ &StackAddrAsyncEscape, "Address of stack-allocated memory is captured"};
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
@@ -170,10 +169,6 @@ void StackAddrEscapeChecker::EmitReturnLeakError(CheckerContext &C,
ExplodedNode *N = C.generateNonFatalErrorNode();
if (!N)
return;
- if (!BT_returnstack)
- BT_returnstack = std::make_unique<BugType>(
- CheckNames[CK_StackAddrEscapeChecker],
- "Return of address to stack-allocated memory");
// Generate a report for this bug.
SmallString<128> buf;
@@ -184,7 +179,7 @@ void StackAddrEscapeChecker::EmitReturnLeakError(CheckerContext &C,
EmitReturnedAsPartOfError(os, C.getSVal(RetE), R);
auto report =
- std::make_unique<PathSensitiveBugReport>(*BT_returnstack, os.str(), N);
+ std::make_unique<PathSensitiveBugReport>(ReturnStack, os.str(), N);
report->addRange(RetE->getSourceRange());
if (range.isValid())
report->addRange(range);
@@ -215,16 +210,12 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
ExplodedNode *N = C.generateNonFatalErrorNode();
if (!N)
continue;
- if (!BT_capturedstackasync)
- BT_capturedstackasync = std::make_unique<BugType>(
- CheckNames[CK_StackAddrAsyncEscapeChecker],
- "Address of stack-allocated memory is captured");
SmallString<128> Buf;
llvm::raw_svector_ostream Out(Buf);
SourceRange Range = genName(Out, Region, C.getASTContext());
Out << " is captured by an asynchronously-executed block";
- auto Report = std::make_unique<PathSensitiveBugReport>(
- *BT_capturedstackasync, Out.str(), N);
+ auto Report = std::make_unique<PathSensitiveBugReport>(CapturedStackAsync,
+ Out.str(), N);
if (Range.isValid())
Report->addRange(Range);
C.emitReport(std::move(Report));
@@ -233,7 +224,7 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
void StackAddrEscapeChecker::checkPreCall(const CallEvent &Call,
CheckerContext &C) const {
- if (!ChecksEnabled[CK_StackAddrAsyncEscapeChecker])
+ if (!StackAddrAsyncEscape.isEnabled())
return;
if (!Call.isGlobalCFunction("dispatch_after") &&
!Call.isGlobalCFunction("dispatch_async"))
@@ -357,7 +348,7 @@ FindEscapingStackRegions(CheckerContext &C, const Expr *RetE, SVal RetVal) {
void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
CheckerContext &C) const {
- if (!ChecksEnabled[CK_StackAddrEscapeChecker])
+ if (!StackAddrEscape.isEnabled())
return;
const Expr *RetE = RS->getRetValue();
@@ -456,7 +447,7 @@ static bool isInvalidatedSymbolRegion(const MemRegion *Region) {
void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
CheckerContext &Ctx) const {
- if (!ChecksEnabled[CK_StackAddrEscapeChecker])
+ if (!StackAddrEscape.isEnabled())
return;
ExplodedNode *Node = Ctx.getPredecessor();
@@ -581,11 +572,6 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
if (!N)
return;
- if (!BT_stackleak)
- BT_stackleak =
- std::make_unique<BugType>(CheckNames[CK_StackAddrEscapeChecker],
- "Stack address leaks outside of stack frame");
-
for (const auto &P : Cb.V) {
const MemRegion *Referrer = P.first->getBaseRegion();
const MemRegion *Referred = P.second;
@@ -604,7 +590,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
Out << " is still referred to by a temporary object on the stack"
<< CommonSuffix;
auto Report =
- std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str(), N);
+ std::make_unique<PathSensitiveBugReport>(StackLeak, Out.str(), N);
if (Range.isValid())
Report->addRange(Range);
Ctx.emitReport(std::move(Report));
@@ -618,7 +604,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
Out << " is still referred to by the " << *ReferrerVariable << CommonSuffix;
auto Report =
- std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str(), N);
+ std::make_unique<PathSensitiveBugReport>(StackLeak, Out.str(), N);
if (Range.isValid())
Report->addRange(Range);
@@ -626,23 +612,14 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
}
}
-void ento::registerStackAddrEscapeBase(CheckerManager &mgr) {
- mgr.registerChecker<StackAddrEscapeChecker>();
-}
-
-bool ento::shouldRegisterStackAddrEscapeBase(const CheckerManager &mgr) {
- return true;
-}
-
-#define REGISTER_CHECKER(name) \
- void ento::register##name(CheckerManager &Mgr) { \
- StackAddrEscapeChecker *Chk = Mgr.getChecker<StackAddrEscapeChecker>(); \
- Chk->ChecksEnabled[StackAddrEscapeChecker::CK_##name] = true; \
- Chk->CheckNames[StackAddrEscapeChecker::CK_##name] = \
- Mgr.getCurrentCheckerName(); \
+#define REGISTER_CHECKER(NAME) \
+ void ento::register##NAME##Checker(CheckerManager &Mgr) { \
+ Mgr.getChecker<StackAddrEscapeChecker>()->NAME.enable(Mgr); \
} \
\
- bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
+ bool ento::shouldRegister##NAME##Checker(const CheckerManager &) { \
+ return true; \
+ }
-REGISTER_CHECKER(StackAddrEscapeChecker)
-REGISTER_CHECKER(StackAddrAsyncEscapeChecker)
+REGISTER_CHECKER(StackAddrEscape)
+REGISTER_CHECKER(StackAddrAsyncEscape)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index f1a25a7..4ddf8fd 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -868,7 +868,8 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
QualType T = Ex->getTypeOfArgument();
for (ExplodedNode *N : CheckedSet) {
- if (Ex->getKind() == UETT_SizeOf) {
+ if (Ex->getKind() == UETT_SizeOf || Ex->getKind() == UETT_DataSizeOf ||
+ Ex->getKind() == UETT_CountOf) {
if (!T->isIncompleteType() && !T->isConstantSizeType()) {
assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 8535384..fe70558 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -1227,7 +1227,7 @@ void ExprEngine::VisitAttributedStmt(const AttributedStmt *A,
for (const auto *Attr : getSpecificAttrs<CXXAssumeAttr>(A->getAttrs())) {
for (ExplodedNode *N : CheckerPreStmt) {
- Visit(Attr->getAssumption(), N, EvalSet);
+ Visit(Attr->getAssumption()->IgnoreParens(), N, EvalSet);
}
}
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 3e68373..0058a0d 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -1219,6 +1219,16 @@ MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
const ASTContext &Ctx) {
QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();
+ // The address space must be preserved because some target-specific address
+ // spaces influence the size of the pointer value which is represented by the
+ // element region.
+ LangAS AS = elementType.getAddressSpace();
+ if (AS != LangAS::Default) {
+ Qualifiers Quals;
+ Quals.setAddressSpace(AS);
+ T = Ctx.getQualifiedType(T, Quals);
+ }
+
llvm::FoldingSetNodeID ID;
ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
diff --git a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
index 5d392af..7bc34f6 100644
--- a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -43,8 +43,8 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
if (Bodies.count(D->getName()) != 0)
return;
- SourceManager &SM = CI.getSourceManager();
- FileID mainFileID = SM.getMainFileID();
+ llvm::IntrusiveRefCntPtr<SourceManager> SM = CI.getSourceManagerPtr();
+ FileID mainFileID = SM->getMainFileID();
llvm::StringRef modelPath = CI.getAnalyzerOpts().ModelPath;
@@ -80,14 +80,14 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
/*ShouldOwnClient=*/true);
- Instance.getDiagnostics().setSourceManager(&SM);
+ Instance.getDiagnostics().setSourceManager(SM.get());
// The instance wants to take ownership, however DisableFree frontend option
// is set to true to avoid double free issues
- Instance.setFileManager(&CI.getFileManager());
- Instance.setSourceManager(&SM);
+ Instance.setFileManager(CI.getFileManagerPtr());
+ Instance.setSourceManager(SM);
Instance.setPreprocessor(CI.getPreprocessorPtr());
- Instance.setASTContext(&CI.getASTContext());
+ Instance.setASTContext(CI.getASTContextPtr());
Instance.getPreprocessor().InitializeForModelFile();
@@ -108,5 +108,5 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
// the main file id is changed to the model file during parsing and it needs
// to be reset to the former main file id after parsing of the model file
// is done.
- SM.setMainFileID(mainFileID);
+ SM->setMainFileID(mainFileID);
}
diff --git a/clang/lib/Tooling/CompilationDatabase.cpp b/clang/lib/Tooling/CompilationDatabase.cpp
index d5fc216..860457a 100644
--- a/clang/lib/Tooling/CompilationDatabase.cpp
+++ b/clang/lib/Tooling/CompilationDatabase.cpp
@@ -241,9 +241,8 @@ static bool stripPositionalArgs(std::vector<const char *> Args,
llvm::raw_string_ostream Output(ErrorMsg);
TextDiagnosticPrinter DiagnosticPrinter(Output, DiagOpts);
UnusedInputDiagConsumer DiagClient(DiagnosticPrinter);
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts,
- &DiagClient, false);
+ DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts, &DiagClient,
+ false);
// The clang executable path isn't required since the jobs the driver builds
// will not be executed.
diff --git a/clang/lib/Tooling/Core/Replacement.cpp b/clang/lib/Tooling/Core/Replacement.cpp
index 1506218..10bdc22 100644
--- a/clang/lib/Tooling/Core/Replacement.cpp
+++ b/clang/lib/Tooling/Core/Replacement.cpp
@@ -581,12 +581,11 @@ llvm::Expected<std::string> applyAllReplacements(StringRef Code,
if (Replaces.empty())
return Code.str();
- IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
- new llvm::vfs::InMemoryFileSystem);
+ auto InMemoryFileSystem =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
FileManager Files(FileSystemOptions(), InMemoryFileSystem);
DiagnosticOptions DiagOpts;
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), DiagOpts);
+ DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts);
SourceManager SourceMgr(Diagnostics, Files);
Rewriter Rewrite(SourceMgr, LangOptions());
InMemoryFileSystem->addFile(
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 8ce2706..b2b61de7 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -605,8 +605,8 @@ DependencyScanningWorker::DependencyScanningWorker(
switch (Service.getMode()) {
case ScanningMode::DependencyDirectivesScan:
- DepFS =
- new DependencyScanningWorkerFilesystem(Service.getSharedCache(), FS);
+ DepFS = llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
+ Service.getSharedCache(), FS);
BaseFS = DepFS;
break;
case ScanningMode::CanonicalPreprocessing:
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index 37f8b94..d67178c 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -144,30 +144,8 @@ static void optimizeDiagnosticOpts(DiagnosticOptions &Opts,
static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD) {
BuildInvocation.getMutFileSystemOpts().WorkingDir.clear();
- if (BuildInvocation.getCodeGenOpts().DwarfVersion) {
- // It is necessary to explicitly set the DebugCompilationDir
- // to a common directory (e.g. root) if IgnoreCWD is true.
- // When IgnoreCWD is true, the module's content should not
- // depend on the current working directory. However, if dwarf
- // information is needed (when CGOpts.DwarfVersion is
- // non-zero), then CGOpts.DebugCompilationDir must be
- // populated, because otherwise the current working directory
- // will be automatically embedded in the dwarf information in
- // the pcm, contradicting the assumption that it is safe to
- // ignore the CWD. Thus in such cases,
- // CGOpts.DebugCompilationDir is explicitly set to a common
- // directory.
- // FIXME: It is still excessive to create a copy of
- // CodeGenOpts for each module. Since we do not modify the
- // CodeGenOpts otherwise per module, the following code
- // ends up generating identical CodeGenOpts for each module
- // with DebugCompilationDir pointing to the root directory.
- // We can optimize this away by creating a _single_ copy of
- // CodeGenOpts whose DebugCompilationDir points to the root
- // directory and reuse it across modules.
- BuildInvocation.getMutCodeGenOpts().DebugCompilationDir =
- llvm::sys::path::root_path(CWD);
- }
+ BuildInvocation.getMutCodeGenOpts().DebugCompilationDir.clear();
+ BuildInvocation.getMutCodeGenOpts().CoverageCompilationDir.clear();
}
static std::vector<std::string> splitString(std::string S, char Separator) {
diff --git a/clang/lib/Tooling/Refactoring.cpp b/clang/lib/Tooling/Refactoring.cpp
index d2b0b37..9b1af237 100644
--- a/clang/lib/Tooling/Refactoring.cpp
+++ b/clang/lib/Tooling/Refactoring.cpp
@@ -39,9 +39,8 @@ int RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) {
LangOptions DefaultLangOptions;
DiagnosticOptions DiagOpts;
TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), DiagOpts);
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts,
- &DiagnosticPrinter, false);
+ DiagnosticsEngine Diagnostics(DiagnosticIDs::create(), DiagOpts,
+ &DiagnosticPrinter, false);
SourceManager Sources(Diagnostics, getFiles());
Rewriter Rewrite(Sources, DefaultLangOptions);
diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 5333956..45dfdf4 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -212,8 +212,8 @@ bool runToolOnCodeWithArgs(
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
- llvm::IntrusiveRefCntPtr<FileManager> Files(
- new FileManager(FileSystemOptions(), VFS));
+ llvm::IntrusiveRefCntPtr<FileManager> Files =
+ llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions(), VFS);
ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster();
ToolInvocation Invocation(
getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileNameRef), FileNameRef),
@@ -227,10 +227,11 @@ bool runToolOnCodeWithArgs(
const Twine &ToolName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
const FileContentMappings &VirtualMappedFiles) {
- llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
- new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
- llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
- new llvm::vfs::InMemoryFileSystem);
+ auto OverlayFileSystem =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(
+ llvm::vfs::getRealFileSystem());
+ auto InMemoryFileSystem =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
SmallString<1024> CodeStorage;
@@ -403,7 +404,7 @@ bool ToolInvocation::run() {
}
const std::unique_ptr<driver::Driver> Driver(
- newDriver(&*Diagnostics, BinaryName, &Files->getVirtualFileSystem()));
+ newDriver(&*Diagnostics, BinaryName, Files->getVirtualFileSystemPtr()));
// The "input file not found" diagnostics from the driver are useful.
// The driver is only aware of the VFS working directory, but some clients
// change this at the FileManager level instead.
@@ -473,10 +474,13 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations,
IntrusiveRefCntPtr<FileManager> Files)
: Compilations(Compilations), SourcePaths(SourcePaths),
PCHContainerOps(std::move(PCHContainerOps)),
- OverlayFileSystem(new llvm::vfs::OverlayFileSystem(std::move(BaseFS))),
- InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
+ OverlayFileSystem(llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(
+ std::move(BaseFS))),
+ InMemoryFileSystem(
+ llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()),
Files(Files ? Files
- : new FileManager(FileSystemOptions(), OverlayFileSystem)) {
+ : llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions(),
+ OverlayFileSystem)) {
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
appendArgumentsAdjuster(getClangStripOutputAdjuster());
appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
@@ -692,13 +696,15 @@ std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
std::vector<std::unique_ptr<ASTUnit>> ASTs;
ASTBuilderAction Action(ASTs);
- llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
- new llvm::vfs::OverlayFileSystem(std::move(BaseFS)));
- llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
- new llvm::vfs::InMemoryFileSystem);
+ auto OverlayFileSystem =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(
+ std::move(BaseFS));
+ auto InMemoryFileSystem =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
- llvm::IntrusiveRefCntPtr<FileManager> Files(
- new FileManager(FileSystemOptions(), OverlayFileSystem));
+ llvm::IntrusiveRefCntPtr<FileManager> Files =
+ llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions(),
+ OverlayFileSystem);
ToolInvocation Invocation(
getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileName), FileName),