aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp20
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp80
-rw-r--r--clang/lib/AST/ByteCode/Interp.h1
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp36
-rw-r--r--clang/lib/AST/ByteCode/Opcodes.td3
-rw-r--r--clang/lib/AST/ByteCode/Program.cpp3
-rw-r--r--clang/lib/AST/ComputeDependence.cpp2
-rw-r--r--clang/lib/AST/ExprConstant.cpp584
-rw-r--r--clang/lib/AST/JSONNodeDumper.cpp21
-rw-r--r--clang/lib/AST/OpenMPClause.cpp20
-rw-r--r--clang/lib/AST/StmtProfile.cpp6
-rw-r--r--clang/lib/AST/TextNodeDumper.cpp14
-rw-r--r--clang/lib/Analysis/ExprMutationAnalyzer.cpp10
-rw-r--r--clang/lib/Analysis/LifetimeSafety/Dataflow.h14
-rw-r--r--clang/lib/Analysis/LifetimeSafety/Facts.cpp15
-rw-r--r--clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp2
-rw-r--r--clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp1
-rw-r--r--clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp2
-rw-r--r--clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp135
-rw-r--r--clang/lib/Basic/BuiltinTargetFeatures.h2
-rw-r--r--clang/lib/Basic/OpenMPKinds.cpp24
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenStmt.cpp2
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp12
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp69
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp5
-rw-r--r--clang/lib/CodeGen/CodeGenPGO.cpp9
-rw-r--r--clang/lib/CodeGen/TargetBuiltins/ARM.cpp32
-rw-r--r--clang/lib/CodeGen/Targets/AArch64.cpp9
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPU.cpp15
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp24
-rw-r--r--clang/lib/Driver/ToolChains/HLSL.cpp4
-rw-r--r--clang/lib/Driver/ToolChains/HLSL.h2
-rw-r--r--clang/lib/Format/Format.cpp12
-rw-r--r--clang/lib/Format/WhitespaceManager.cpp18
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp4
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp14
-rw-r--r--clang/lib/Headers/avx512bwintrin.h36
-rw-r--r--clang/lib/Headers/avx512cdintrin.h4
-rw-r--r--clang/lib/Headers/avx512dqintrin.h36
-rw-r--r--clang/lib/Headers/avx512fintrin.h22
-rw-r--r--clang/lib/Headers/avx512vlcdintrin.h12
-rw-r--r--clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h72
-rw-r--r--clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h12
-rw-r--r--clang/lib/Headers/hlsl/hlsl_intrinsics.h61
-rw-r--r--clang/lib/Headers/llvm_libc_wrappers/stdlib.h4
-rw-r--r--clang/lib/Interpreter/Interpreter.cpp49
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp22
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp90
-rw-r--r--clang/lib/Parse/ParseStmt.cpp14
-rw-r--r--clang/lib/Sema/Sema.cpp42
-rw-r--r--clang/lib/Sema/SemaAMDGPU.cpp2
-rw-r--r--clang/lib/Sema/SemaBoundsSafety.cpp23
-rw-r--r--clang/lib/Sema/SemaConcept.cpp58
-rw-r--r--clang/lib/Sema/SemaDecl.cpp11
-rw-r--r--clang/lib/Sema/SemaExpr.cpp20
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp64
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp30
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp130
-rw-r--r--clang/lib/Sema/SemaTemplateDeductionGuide.cpp1
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp182
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp9
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp11
-rw-r--r--clang/lib/Sema/TreeTransform.h51
-rw-r--r--clang/lib/Serialization/ASTReader.cpp16
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp11
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp3
-rw-r--r--clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp184
-rw-r--r--clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h67
-rw-r--r--clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp36
-rw-r--r--clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp75
-rw-r--r--clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp4
-rw-r--r--clang/lib/Tooling/Syntax/TokenBufferTokenManager.cpp2
72 files changed, 1962 insertions, 730 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 84f7e62..20836f6 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2508,7 +2508,7 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
};
if (std::optional<bool> BoolValue = getBoolValue(Condition)) {
- if (BoolValue)
+ if (*BoolValue)
return visitChildExpr(TrueExpr);
return visitChildExpr(FalseExpr);
}
@@ -3235,7 +3235,8 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return this->visitInitializer(E->getArg(0));
// Zero initialization.
- if (E->requiresZeroInitialization()) {
+ bool ZeroInit = E->requiresZeroInitialization();
+ if (ZeroInit) {
const Record *R = getRecord(E->getType());
if (!this->visitZeroRecordInitializer(R, E))
@@ -3246,6 +3247,19 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return true;
}
+ // Avoid materializing a temporary for an elidable copy/move constructor.
+ if (!ZeroInit && E->isElidable()) {
+ const Expr *SrcObj = E->getArg(0);
+ assert(SrcObj->isTemporaryObject(Ctx.getASTContext(), Ctor->getParent()));
+ assert(Ctx.getASTContext().hasSameUnqualifiedType(E->getType(),
+ SrcObj->getType()));
+ if (const auto *ME = dyn_cast<MaterializeTemporaryExpr>(SrcObj)) {
+ if (!this->emitCheckFunctionDecl(Ctor, E))
+ return false;
+ return this->visitInitializer(ME->getSubExpr());
+ }
+ }
+
const Function *Func = getFunction(Ctor);
if (!Func)
@@ -4175,7 +4189,7 @@ bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {
StmtExprScope<Emitter> SS(this);
const CompoundStmt *CS = E->getSubStmt();
- const Stmt *Result = CS->getStmtExprResult();
+ const Stmt *Result = CS->body_back();
for (const Stmt *S : CS->body()) {
if (S != Result) {
if (!this->visitStmt(S))
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index a2fb0fb..1f2ae92 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -919,33 +919,8 @@ bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return true;
}
-static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
-
- if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
- const SourceLocation &Loc = S.Current->getLocation(OpPC);
- S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
- return false;
- }
-
- if (S.checkingPotentialConstantExpression() && S.Current->getDepth() != 0)
- return false;
-
- if (F->isValid() && F->hasBody() && F->isConstexpr())
- return true;
-
- const FunctionDecl *DiagDecl = F->getDecl();
- const FunctionDecl *Definition = nullptr;
- DiagDecl->getBody(Definition);
-
- if (!Definition && S.checkingPotentialConstantExpression() &&
- DiagDecl->isConstexpr()) {
- return false;
- }
-
- // Implicitly constexpr.
- if (F->isLambdaStaticInvoker())
- return true;
-
+static bool diagnoseCallableDecl(InterpState &S, CodePtr OpPC,
+ const FunctionDecl *DiagDecl) {
// Bail out if the function declaration itself is invalid. We will
// have produced a relevant diagnostic while parsing it, so just
// note the problematic sub-expression.
@@ -953,11 +928,10 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
return Invalid(S, OpPC);
// Diagnose failed assertions specially.
- if (S.Current->getLocation(OpPC).isMacroID() &&
- F->getDecl()->getIdentifier()) {
+ if (S.Current->getLocation(OpPC).isMacroID() && DiagDecl->getIdentifier()) {
// FIXME: Instead of checking for an implementation-defined function,
// check and evaluate the assert() macro.
- StringRef Name = F->getDecl()->getName();
+ StringRef Name = DiagDecl->getName();
bool AssertFailed =
Name == "__assert_rtn" || Name == "__assert_fail" || Name == "_wassert";
if (AssertFailed) {
@@ -1004,7 +978,7 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
// for a constant expression. It might be defined at the point we're
// actually calling it.
bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
- bool IsDefined = F->isDefined();
+ bool IsDefined = DiagDecl->isDefined();
if (!IsDefined && !IsExtern && DiagDecl->isConstexpr() &&
S.checkingPotentialConstantExpression())
return false;
@@ -1027,6 +1001,35 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
return false;
}
+static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
+ if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) {
+ const SourceLocation &Loc = S.Current->getLocation(OpPC);
+ S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
+ return false;
+ }
+
+ if (S.checkingPotentialConstantExpression() && S.Current->getDepth() != 0)
+ return false;
+
+ if (F->isValid() && F->hasBody() && F->isConstexpr())
+ return true;
+
+ const FunctionDecl *DiagDecl = F->getDecl();
+ const FunctionDecl *Definition = nullptr;
+ DiagDecl->getBody(Definition);
+
+ if (!Definition && S.checkingPotentialConstantExpression() &&
+ DiagDecl->isConstexpr()) {
+ return false;
+ }
+
+ // Implicitly constexpr.
+ if (F->isLambdaStaticInvoker())
+ return true;
+
+ return diagnoseCallableDecl(S, OpPC, DiagDecl);
+}
+
static bool CheckCallDepth(InterpState &S, CodePtr OpPC) {
if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
S.FFDiag(S.Current->getSource(OpPC),
@@ -1500,6 +1503,21 @@ bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return CheckActive(S, OpPC, Ptr, AK_Destroy);
}
+/// Opcode. Check if the function decl can be called at compile time.
+bool CheckFunctionDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *FD) {
+ if (S.checkingPotentialConstantExpression() && S.Current->getDepth() != 0)
+ return false;
+
+ const FunctionDecl *Definition = nullptr;
+ const Stmt *Body = FD->getBody(Definition);
+
+ if (Definition && Body &&
+ (Definition->isConstexpr() || Definition->hasAttr<MSConstexprAttr>()))
+ return true;
+
+ return diagnoseCallableDecl(S, OpPC, FD);
+}
+
static void compileFunction(InterpState &S, const Function *Func) {
const FunctionDecl *Definition = Func->getDecl()->getDefinition();
if (!Definition)
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 6877b03..c16408c 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -117,6 +117,7 @@ bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
bool TargetIsUCharOrByte);
bool CheckBCPResult(InterpState &S, const Pointer &Ptr);
bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
+bool CheckFunctionDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *FD);
bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
const FixedPoint &FP);
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 9991e36..0ef130c 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -3831,6 +3831,42 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
return Result;
});
+ case clang::X86::BI__builtin_ia32_ktestcqi:
+ case clang::X86::BI__builtin_ia32_ktestchi:
+ case clang::X86::BI__builtin_ia32_ktestcsi:
+ case clang::X86::BI__builtin_ia32_ktestcdi:
+ return interp__builtin_elementwise_int_binop(
+ S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
+ return APInt(sizeof(unsigned char) * 8, (~A & B) == 0);
+ });
+
+ case clang::X86::BI__builtin_ia32_ktestzqi:
+ case clang::X86::BI__builtin_ia32_ktestzhi:
+ case clang::X86::BI__builtin_ia32_ktestzsi:
+ case clang::X86::BI__builtin_ia32_ktestzdi:
+ return interp__builtin_elementwise_int_binop(
+ S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
+ return APInt(sizeof(unsigned char) * 8, (A & B) == 0);
+ });
+
+ case clang::X86::BI__builtin_ia32_kortestcqi:
+ case clang::X86::BI__builtin_ia32_kortestchi:
+ case clang::X86::BI__builtin_ia32_kortestcsi:
+ case clang::X86::BI__builtin_ia32_kortestcdi:
+ return interp__builtin_elementwise_int_binop(
+ S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
+ return APInt(sizeof(unsigned char) * 8, ~(A | B) == 0);
+ });
+
+ case clang::X86::BI__builtin_ia32_kortestzqi:
+ case clang::X86::BI__builtin_ia32_kortestzhi:
+ case clang::X86::BI__builtin_ia32_kortestzsi:
+ case clang::X86::BI__builtin_ia32_kortestzdi:
+ return interp__builtin_elementwise_int_binop(
+ S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
+ return APInt(sizeof(unsigned char) * 8, (A | B) == 0);
+ });
+
case clang::X86::BI__builtin_ia32_lzcnt_u16:
case clang::X86::BI__builtin_ia32_lzcnt_u32:
case clang::X86::BI__builtin_ia32_lzcnt_u64:
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 1c17ad9e..a2eaa61 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -53,6 +53,7 @@ def ArgBool : ArgType { let Name = "bool"; }
def ArgFixedPoint : ArgType { let Name = "FixedPoint"; let AsRef = true; }
def ArgFunction : ArgType { let Name = "const Function *"; }
+def ArgFunctionDecl : ArgType { let Name = "const FunctionDecl *"; }
def ArgRecordDecl : ArgType { let Name = "const RecordDecl *"; }
def ArgRecordField : ArgType { let Name = "const Record::Field *"; }
def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; }
@@ -422,6 +423,8 @@ def CheckLiteralType : Opcode {
def CheckArraySize : Opcode { let Args = [ArgUint64]; }
+def CheckFunctionDecl : Opcode { let Args = [ArgFunctionDecl]; }
+
// [] -> [Value]
def GetGlobal : AccessOpcode;
def GetGlobalUnchecked : AccessOpcode;
diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp
index 4d34e0b..c468303 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -197,7 +197,8 @@ UnsignedOrNone Program::createGlobal(const ValueDecl *VD, const Expr *Init) {
// global variable and points to the block we just created.
if (auto DummyIt = DummyVariables.find(Redecl);
DummyIt != DummyVariables.end()) {
- assert(!Globals[DummyIt->second]->block()->hasPointers());
+ Global *Dummy = Globals[DummyIt->second];
+ Dummy->block()->movePointersTo(NewGlobal->block());
Globals[DummyIt->second] = NewGlobal;
DummyVariables.erase(DummyIt);
}
diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index e0cf0de..638080e 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -178,7 +178,7 @@ ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) {
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
// Propagate dependence of the result.
if (const auto *CompoundExprResult =
- dyn_cast_or_null<ValueStmt>(E->getSubStmt()->getStmtExprResult()))
+ dyn_cast_or_null<ValueStmt>(E->getSubStmt()->body_back()))
if (const Expr *ResultExpr = CompoundExprResult->getExprStmt())
D |= ResultExpr->getDependence();
// Note: we treat a statement-expression in a dependent context as always
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 193f87c..972d9fe 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -3829,6 +3829,351 @@ static bool CheckArraySize(EvalInfo &Info, const ConstantArrayType *CAT,
/*Diag=*/true);
}
+static bool handleScalarCast(EvalInfo &Info, const FPOptions FPO, const Expr *E,
+ QualType SourceTy, QualType DestTy,
+ APValue const &Original, APValue &Result) {
+ // boolean must be checked before integer
+ // since IsIntegerType() is true for bool
+ if (SourceTy->isBooleanType()) {
+ if (DestTy->isBooleanType()) {
+ Result = Original;
+ return true;
+ }
+ if (DestTy->isIntegerType() || DestTy->isRealFloatingType()) {
+ bool BoolResult;
+ if (!HandleConversionToBool(Original, BoolResult))
+ return false;
+ uint64_t IntResult = BoolResult;
+ QualType IntType = DestTy->isIntegerType()
+ ? DestTy
+ : Info.Ctx.getIntTypeForBitwidth(64, false);
+ Result = APValue(Info.Ctx.MakeIntValue(IntResult, IntType));
+ }
+ if (DestTy->isRealFloatingType()) {
+ APValue Result2 = APValue(APFloat(0.0));
+ if (!HandleIntToFloatCast(Info, E, FPO,
+ Info.Ctx.getIntTypeForBitwidth(64, false),
+ Result.getInt(), DestTy, Result2.getFloat()))
+ return false;
+ Result = Result2;
+ }
+ return true;
+ }
+ if (SourceTy->isIntegerType()) {
+ if (DestTy->isRealFloatingType()) {
+ Result = APValue(APFloat(0.0));
+ return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+ DestTy, Result.getFloat());
+ }
+ if (DestTy->isBooleanType()) {
+ bool BoolResult;
+ if (!HandleConversionToBool(Original, BoolResult))
+ return false;
+ uint64_t IntResult = BoolResult;
+ Result = APValue(Info.Ctx.MakeIntValue(IntResult, DestTy));
+ return true;
+ }
+ if (DestTy->isIntegerType()) {
+ Result = APValue(
+ HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+ return true;
+ }
+ } else if (SourceTy->isRealFloatingType()) {
+ if (DestTy->isRealFloatingType()) {
+ Result = Original;
+ return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+ Result.getFloat());
+ }
+ if (DestTy->isBooleanType()) {
+ bool BoolResult;
+ if (!HandleConversionToBool(Original, BoolResult))
+ return false;
+ uint64_t IntResult = BoolResult;
+ Result = APValue(Info.Ctx.MakeIntValue(IntResult, DestTy));
+ return true;
+ }
+ if (DestTy->isIntegerType()) {
+ Result = APValue(APSInt());
+ return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+ DestTy, Result.getInt());
+ }
+ }
+
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ return false;
+}
+
+// do the heavy lifting for casting to aggregate types
+// because we have to deal with bitfields specially
+static bool constructAggregate(EvalInfo &Info, const FPOptions FPO,
+ const Expr *E, APValue &Result,
+ QualType ResultType,
+ SmallVectorImpl<APValue> &Elements,
+ SmallVectorImpl<QualType> &ElTypes) {
+
+ SmallVector<std::tuple<APValue *, QualType, unsigned>> WorkList = {
+ {&Result, ResultType, 0}};
+
+ unsigned ElI = 0;
+ while (!WorkList.empty() && ElI < Elements.size()) {
+ auto [Res, Type, BitWidth] = WorkList.pop_back_val();
+
+ if (Type->isRealFloatingType()) {
+ if (!handleScalarCast(Info, FPO, E, ElTypes[ElI], Type, Elements[ElI],
+ *Res))
+ return false;
+ ElI++;
+ continue;
+ }
+ if (Type->isIntegerType()) {
+ if (!handleScalarCast(Info, FPO, E, ElTypes[ElI], Type, Elements[ElI],
+ *Res))
+ return false;
+ if (BitWidth > 0) {
+ if (!Res->isInt())
+ return false;
+ APSInt &Int = Res->getInt();
+ unsigned OldBitWidth = Int.getBitWidth();
+ unsigned NewBitWidth = BitWidth;
+ if (NewBitWidth < OldBitWidth)
+ Int = Int.trunc(NewBitWidth).extend(OldBitWidth);
+ }
+ ElI++;
+ continue;
+ }
+ if (Type->isVectorType()) {
+ QualType ElTy = Type->castAs<VectorType>()->getElementType();
+ unsigned NumEl = Type->castAs<VectorType>()->getNumElements();
+ SmallVector<APValue> Vals(NumEl);
+ for (unsigned I = 0; I < NumEl; ++I) {
+ if (!handleScalarCast(Info, FPO, E, ElTypes[ElI], ElTy, Elements[ElI],
+ Vals[I]))
+ return false;
+ ElI++;
+ }
+ *Res = APValue(Vals.data(), NumEl);
+ continue;
+ }
+ if (Type->isConstantArrayType()) {
+ QualType ElTy = cast<ConstantArrayType>(Info.Ctx.getAsArrayType(Type))
+ ->getElementType();
+ uint64_t Size =
+ cast<ConstantArrayType>(Info.Ctx.getAsArrayType(Type))->getZExtSize();
+ *Res = APValue(APValue::UninitArray(), Size, Size);
+ for (int64_t I = Size - 1; I > -1; --I)
+ WorkList.emplace_back(&Res->getArrayInitializedElt(I), ElTy, 0u);
+ continue;
+ }
+ if (Type->isRecordType()) {
+ const RecordDecl *RD = Type->getAsRecordDecl();
+
+ unsigned NumBases = 0;
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+ NumBases = CXXRD->getNumBases();
+
+ *Res = APValue(APValue::UninitStruct(), NumBases,
+ std::distance(RD->field_begin(), RD->field_end()));
+
+ SmallVector<std::tuple<APValue *, QualType, unsigned>> ReverseList;
+ // we need to traverse backwards
+ // Visit the base classes.
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (CXXRD->getNumBases() > 0) {
+ assert(CXXRD->getNumBases() == 1);
+ const CXXBaseSpecifier &BS = CXXRD->bases_begin()[0];
+ ReverseList.emplace_back(&Res->getStructBase(0), BS.getType(), 0u);
+ }
+ }
+
+ // Visit the fields.
+ for (FieldDecl *FD : RD->fields()) {
+ unsigned FDBW = 0;
+ if (FD->isUnnamedBitField())
+ continue;
+ if (FD->isBitField()) {
+ FDBW = FD->getBitWidthValue();
+ }
+
+ ReverseList.emplace_back(&Res->getStructField(FD->getFieldIndex()),
+ FD->getType(), FDBW);
+ }
+
+ std::reverse(ReverseList.begin(), ReverseList.end());
+ llvm::append_range(WorkList, ReverseList);
+ continue;
+ }
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ return false;
+ }
+ return true;
+}
+
+static bool handleElementwiseCast(EvalInfo &Info, const Expr *E,
+ const FPOptions FPO,
+ SmallVectorImpl<APValue> &Elements,
+ SmallVectorImpl<QualType> &SrcTypes,
+ SmallVectorImpl<QualType> &DestTypes,
+ SmallVectorImpl<APValue> &Results) {
+
+ assert((Elements.size() == SrcTypes.size()) &&
+ (Elements.size() == DestTypes.size()));
+
+ for (unsigned I = 0, ESz = Elements.size(); I < ESz; ++I) {
+ APValue Original = Elements[I];
+ QualType SourceTy = SrcTypes[I];
+ QualType DestTy = DestTypes[I];
+
+ if (!handleScalarCast(Info, FPO, E, SourceTy, DestTy, Original, Results[I]))
+ return false;
+ }
+ return true;
+}
+
+static unsigned elementwiseSize(EvalInfo &Info, QualType BaseTy) {
+
+ SmallVector<QualType> WorkList = {BaseTy};
+
+ unsigned Size = 0;
+ while (!WorkList.empty()) {
+ QualType Type = WorkList.pop_back_val();
+ if (Type->isRealFloatingType() || Type->isIntegerType() ||
+ Type->isBooleanType()) {
+ ++Size;
+ continue;
+ }
+ if (Type->isVectorType()) {
+ unsigned NumEl = Type->castAs<VectorType>()->getNumElements();
+ Size += NumEl;
+ continue;
+ }
+ if (Type->isConstantArrayType()) {
+ QualType ElTy = cast<ConstantArrayType>(Info.Ctx.getAsArrayType(Type))
+ ->getElementType();
+ uint64_t ArrSize =
+ cast<ConstantArrayType>(Info.Ctx.getAsArrayType(Type))->getZExtSize();
+ for (uint64_t I = 0; I < ArrSize; ++I) {
+ WorkList.push_back(ElTy);
+ }
+ continue;
+ }
+ if (Type->isRecordType()) {
+ const RecordDecl *RD = Type->getAsRecordDecl();
+
+ // Visit the base classes.
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (CXXRD->getNumBases() > 0) {
+ assert(CXXRD->getNumBases() == 1);
+ const CXXBaseSpecifier &BS = CXXRD->bases_begin()[0];
+ WorkList.push_back(BS.getType());
+ }
+ }
+
+ // visit the fields.
+ for (FieldDecl *FD : RD->fields()) {
+ if (FD->isUnnamedBitField())
+ continue;
+ WorkList.push_back(FD->getType());
+ }
+ continue;
+ }
+ }
+ return Size;
+}
+
+static bool hlslAggSplatHelper(EvalInfo &Info, const Expr *E, APValue &SrcVal,
+ QualType &SrcTy) {
+ SrcTy = E->getType();
+
+ if (!Evaluate(SrcVal, Info, E))
+ return false;
+
+ assert(SrcVal.isFloat() || SrcVal.isInt() ||
+ (SrcVal.isVector() && SrcVal.getVectorLength() == 1) &&
+ "Not a valid HLSLAggregateSplatCast.");
+
+ if (SrcVal.isVector()) {
+ assert(SrcTy->isVectorType() && "Type mismatch.");
+ SrcTy = SrcTy->castAs<VectorType>()->getElementType();
+ SrcVal = SrcVal.getVectorElt(0);
+ }
+ return true;
+}
+
+static bool flattenAPValue(EvalInfo &Info, const Expr *E, APValue Value,
+ QualType BaseTy, SmallVectorImpl<APValue> &Elements,
+ SmallVectorImpl<QualType> &Types, unsigned Size) {
+
+ SmallVector<std::pair<APValue, QualType>> WorkList = {{Value, BaseTy}};
+ unsigned Populated = 0;
+ while (!WorkList.empty() && Populated < Size) {
+ auto [Work, Type] = WorkList.pop_back_val();
+
+ if (Work.isFloat() || Work.isInt()) {
+ Elements.push_back(Work);
+ Types.push_back(Type);
+ Populated++;
+ continue;
+ }
+ if (Work.isVector()) {
+ assert(Type->isVectorType() && "Type mismatch.");
+ QualType ElTy = Type->castAs<VectorType>()->getElementType();
+ for (unsigned I = 0; I < Work.getVectorLength() && Populated < Size;
+ I++) {
+ Elements.push_back(Work.getVectorElt(I));
+ Types.push_back(ElTy);
+ Populated++;
+ }
+ continue;
+ }
+ if (Work.isArray()) {
+ assert(Type->isConstantArrayType() && "Type mismatch.");
+ QualType ElTy = cast<ConstantArrayType>(Info.Ctx.getAsArrayType(Type))
+ ->getElementType();
+ for (int64_t I = Work.getArraySize() - 1; I > -1; --I) {
+ WorkList.emplace_back(Work.getArrayInitializedElt(I), ElTy);
+ }
+ continue;
+ }
+
+ if (Work.isStruct()) {
+ assert(Type->isRecordType() && "Type mismatch.");
+
+ const RecordDecl *RD = Type->getAsRecordDecl();
+
+ SmallVector<std::pair<APValue, QualType>> ReverseList;
+ // Visit the fields.
+ for (FieldDecl *FD : RD->fields()) {
+ if (FD->isUnnamedBitField())
+ continue;
+ ReverseList.emplace_back(Work.getStructField(FD->getFieldIndex()),
+ FD->getType());
+ }
+
+ std::reverse(ReverseList.begin(), ReverseList.end());
+ llvm::append_range(WorkList, ReverseList);
+
+ // Visit the base classes.
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (CXXRD->getNumBases() > 0) {
+ assert(CXXRD->getNumBases() == 1);
+ const CXXBaseSpecifier &BS = CXXRD->bases_begin()[0];
+ const APValue &Base = Work.getStructBase(0);
+
+ // Can happen in error cases.
+ if (!Base.isStruct())
+ return false;
+
+ WorkList.emplace_back(Base, BS.getType());
+ }
+ }
+ continue;
+ }
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ return false;
+ }
+ return true;
+}
+
namespace {
/// A handle to a complete object (an object that is not a subobject of
/// another object).
@@ -4639,6 +4984,30 @@ handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, QualType Type,
return Obj && extractSubobject(Info, Conv, Obj, LVal.Designator, RVal, AK);
}
+static bool hlslElementwiseCastHelper(EvalInfo &Info, const Expr *E,
+ QualType DestTy,
+ SmallVectorImpl<APValue> &SrcVals,
+ SmallVectorImpl<QualType> &SrcTypes) {
+ APValue Val;
+ if (!Evaluate(Val, Info, E))
+ return false;
+
+ // must be dealing with a record
+ if (Val.isLValue()) {
+ LValue LVal;
+ LVal.setFrom(Info.Ctx, Val);
+ if (!handleLValueToRValueConversion(Info, E, E->getType(), LVal, Val))
+ return false;
+ }
+
+ unsigned NEls = elementwiseSize(Info, DestTy);
+ // flatten the source
+ if (!flattenAPValue(Info, E, Val, E->getType(), SrcVals, SrcTypes, NEls))
+ return false;
+
+ return true;
+}
+
/// Perform an assignment of Val to LVal. Takes ownership of Val.
static bool handleAssignment(EvalInfo &Info, const Expr *E, const LValue &LVal,
QualType LValType, APValue &Val) {
@@ -8670,6 +9039,25 @@ public:
case CK_UserDefinedConversion:
return StmtVisitorTy::Visit(E->getSubExpr());
+ case CK_HLSLArrayRValue: {
+ const Expr *SubExpr = E->getSubExpr();
+ if (!SubExpr->isGLValue()) {
+ APValue Val;
+ if (!Evaluate(Val, Info, SubExpr))
+ return false;
+ return DerivedSuccess(Val, E);
+ }
+
+ LValue LVal;
+ if (!EvaluateLValue(SubExpr, LVal, Info))
+ return false;
+ APValue RVal;
+ // Note, we use the subexpression's type in order to retain cv-qualifiers.
+ if (!handleLValueToRValueConversion(Info, E, SubExpr->getType(), LVal,
+ RVal))
+ return false;
+ return DerivedSuccess(RVal, E);
+ }
case CK_LValueToRValue: {
LValue LVal;
if (!EvaluateLValue(E->getSubExpr(), LVal, Info))
@@ -10854,6 +11242,42 @@ bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) {
Result = *Value;
return true;
}
+ case CK_HLSLAggregateSplatCast: {
+ APValue Val;
+ QualType ValTy;
+
+ if (!hlslAggSplatHelper(Info, E->getSubExpr(), Val, ValTy))
+ return false;
+
+ unsigned NEls = elementwiseSize(Info, E->getType());
+ // splat our Val
+ SmallVector<APValue> SplatEls(NEls, Val);
+ SmallVector<QualType> SplatType(NEls, ValTy);
+
+ // cast the elements and construct our struct result
+ const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+ if (!constructAggregate(Info, FPO, E, Result, E->getType(), SplatEls,
+ SplatType))
+ return false;
+
+ return true;
+ }
+ case CK_HLSLElementwiseCast: {
+ SmallVector<APValue> SrcEls;
+ SmallVector<QualType> SrcTypes;
+
+ if (!hlslElementwiseCastHelper(Info, E->getSubExpr(), E->getType(), SrcEls,
+ SrcTypes))
+ return false;
+
+ // cast the elements and construct our struct result
+ const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+ if (!constructAggregate(Info, FPO, E, Result, E->getType(), SrcEls,
+ SrcTypes))
+ return false;
+
+ return true;
+ }
}
}
@@ -11349,6 +11773,38 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) {
Elements.push_back(Val.getVectorElt(I));
return Success(Elements, E);
}
+ case CK_HLSLAggregateSplatCast: {
+ APValue Val;
+ QualType ValTy;
+
+ if (!hlslAggSplatHelper(Info, SE, Val, ValTy))
+ return false;
+
+ // cast our Val once.
+ APValue Result;
+ const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+ if (!handleScalarCast(Info, FPO, E, ValTy, VTy->getElementType(), Val,
+ Result))
+ return false;
+
+ SmallVector<APValue, 4> SplatEls(NElts, Result);
+ return Success(SplatEls, E);
+ }
+ case CK_HLSLElementwiseCast: {
+ SmallVector<APValue> SrcVals;
+ SmallVector<QualType> SrcTypes;
+
+ if (!hlslElementwiseCastHelper(Info, SE, E->getType(), SrcVals, SrcTypes))
+ return false;
+
+ const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+ SmallVector<QualType, 4> DestTypes(NElts, VTy->getElementType());
+ SmallVector<APValue, 4> ResultEls(NElts);
+ if (!handleElementwiseCast(Info, E, FPO, SrcVals, SrcTypes, DestTypes,
+ ResultEls))
+ return false;
+ return Success(ResultEls, E);
+ }
default:
return ExprEvaluatorBaseTy::VisitCastExpr(E);
}
@@ -13316,6 +13772,7 @@ namespace {
bool VisitCallExpr(const CallExpr *E) {
return handleCallExpr(E, Result, &This);
}
+ bool VisitCastExpr(const CastExpr *E);
bool VisitInitListExpr(const InitListExpr *E,
QualType AllocType = QualType());
bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E);
@@ -13386,6 +13843,49 @@ static bool MaybeElementDependentArrayFiller(const Expr *FillerExpr) {
return true;
}
+bool ArrayExprEvaluator::VisitCastExpr(const CastExpr *E) {
+ const Expr *SE = E->getSubExpr();
+
+ switch (E->getCastKind()) {
+ default:
+ return ExprEvaluatorBaseTy::VisitCastExpr(E);
+ case CK_HLSLAggregateSplatCast: {
+ APValue Val;
+ QualType ValTy;
+
+ if (!hlslAggSplatHelper(Info, SE, Val, ValTy))
+ return false;
+
+ unsigned NEls = elementwiseSize(Info, E->getType());
+
+ SmallVector<APValue> SplatEls(NEls, Val);
+ SmallVector<QualType> SplatType(NEls, ValTy);
+
+ // cast the elements
+ const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+ if (!constructAggregate(Info, FPO, E, Result, E->getType(), SplatEls,
+ SplatType))
+ return false;
+
+ return true;
+ }
+ case CK_HLSLElementwiseCast: {
+ SmallVector<APValue> SrcEls;
+ SmallVector<QualType> SrcTypes;
+
+ if (!hlslElementwiseCastHelper(Info, SE, E->getType(), SrcEls, SrcTypes))
+ return false;
+
+ // cast the elements
+ const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+ if (!constructAggregate(Info, FPO, E, Result, E->getType(), SrcEls,
+ SrcTypes))
+ return false;
+ return true;
+ }
+ }
+}
+
bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E,
QualType AllocType) {
const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(
@@ -15744,6 +16244,54 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(Val, E);
}
+ case clang::X86::BI__builtin_ia32_ktestcqi:
+ case clang::X86::BI__builtin_ia32_ktestchi:
+ case clang::X86::BI__builtin_ia32_ktestcsi:
+ case clang::X86::BI__builtin_ia32_ktestcdi: {
+ APSInt A, B;
+ if (!EvaluateInteger(E->getArg(0), A, Info) ||
+ !EvaluateInteger(E->getArg(1), B, Info))
+ return false;
+
+ return Success((~A & B) == 0, E);
+ }
+
+ case clang::X86::BI__builtin_ia32_ktestzqi:
+ case clang::X86::BI__builtin_ia32_ktestzhi:
+ case clang::X86::BI__builtin_ia32_ktestzsi:
+ case clang::X86::BI__builtin_ia32_ktestzdi: {
+ APSInt A, B;
+ if (!EvaluateInteger(E->getArg(0), A, Info) ||
+ !EvaluateInteger(E->getArg(1), B, Info))
+ return false;
+
+ return Success((A & B) == 0, E);
+ }
+
+ case clang::X86::BI__builtin_ia32_kortestcqi:
+ case clang::X86::BI__builtin_ia32_kortestchi:
+ case clang::X86::BI__builtin_ia32_kortestcsi:
+ case clang::X86::BI__builtin_ia32_kortestcdi: {
+ APSInt A, B;
+ if (!EvaluateInteger(E->getArg(0), A, Info) ||
+ !EvaluateInteger(E->getArg(1), B, Info))
+ return false;
+
+ return Success(~(A | B) == 0, E);
+ }
+
+ case clang::X86::BI__builtin_ia32_kortestzqi:
+ case clang::X86::BI__builtin_ia32_kortestzhi:
+ case clang::X86::BI__builtin_ia32_kortestzsi:
+ case clang::X86::BI__builtin_ia32_kortestzdi: {
+ APSInt A, B;
+ if (!EvaluateInteger(E->getArg(0), A, Info) ||
+ !EvaluateInteger(E->getArg(1), B, Info))
+ return false;
+
+ return Success((A | B) == 0, E);
+ }
+
case clang::X86::BI__builtin_ia32_lzcnt_u16:
case clang::X86::BI__builtin_ia32_lzcnt_u32:
case clang::X86::BI__builtin_ia32_lzcnt_u64: {
@@ -17192,7 +17740,6 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_NoOp:
case CK_LValueToRValueBitCast:
case CK_HLSLArrayRValue:
- case CK_HLSLElementwiseCast:
return ExprEvaluatorBaseTy::VisitCastExpr(E);
case CK_MemberPointerToBoolean:
@@ -17339,6 +17886,21 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
return Error(E);
return Success(Val.getVectorElt(0), E);
}
+ case CK_HLSLElementwiseCast: {
+ SmallVector<APValue> SrcVals;
+ SmallVector<QualType> SrcTypes;
+
+ if (!hlslElementwiseCastHelper(Info, SubExpr, DestType, SrcVals, SrcTypes))
+ return false;
+
+ // cast our single element
+ const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+ APValue ResultVal;
+ if (!handleScalarCast(Info, FPO, E, SrcTypes[0], DestType, SrcVals[0],
+ ResultVal))
+ return false;
+ return Success(ResultVal, E);
+ }
}
llvm_unreachable("unknown cast resulting in integral value");
@@ -17876,6 +18438,9 @@ bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) {
default:
return ExprEvaluatorBaseTy::VisitCastExpr(E);
+ case CK_HLSLAggregateSplatCast:
+ llvm_unreachable("invalid cast kind for floating value");
+
case CK_IntegralToFloating: {
APSInt IntResult;
const FPOptions FPO = E->getFPFeaturesInEffect(
@@ -17914,6 +18479,23 @@ bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) {
return Error(E);
return Success(Val.getVectorElt(0), E);
}
+ case CK_HLSLElementwiseCast: {
+ SmallVector<APValue> SrcVals;
+ SmallVector<QualType> SrcTypes;
+
+ if (!hlslElementwiseCastHelper(Info, SubExpr, E->getType(), SrcVals,
+ SrcTypes))
+ return false;
+ APValue Val;
+
+ // cast our single element
+ const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+ APValue ResultVal;
+ if (!handleScalarCast(Info, FPO, E, SrcTypes[0], E->getType(), SrcVals[0],
+ ResultVal))
+ return false;
+ return Success(ResultVal, E);
+ }
}
}
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 9f4dba9..89abf88 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -272,15 +272,13 @@ void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc, bool JustFirst) {
JOS.attributeEnd();
}
-void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc,
- bool IsSpelling) {
+void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc) {
PresumedLoc Presumed = SM.getPresumedLoc(Loc);
- unsigned ActualLine = IsSpelling ? SM.getSpellingLineNumber(Loc)
- : SM.getExpansionLineNumber(Loc);
- StringRef ActualFile = SM.getBufferName(Loc);
-
if (Presumed.isValid()) {
- JOS.attribute("offset", SM.getDecomposedLoc(Loc).second);
+ StringRef ActualFile = SM.getBufferName(Loc);
+ auto [FID, FilePos] = SM.getDecomposedLoc(Loc);
+ unsigned ActualLine = SM.getLineNumber(FID, FilePos);
+ JOS.attribute("offset", FilePos);
if (LastLocFilename != ActualFile) {
JOS.attribute("file", ActualFile);
JOS.attribute("line", ActualLine);
@@ -318,18 +316,17 @@ void JSONNodeDumper::writeSourceLocation(SourceLocation Loc) {
if (Expansion != Spelling) {
// If the expansion and the spelling are different, output subobjects
// describing both locations.
- JOS.attributeObject("spellingLoc", [Spelling, this] {
- writeBareSourceLocation(Spelling, /*IsSpelling*/ true);
- });
+ JOS.attributeObject(
+ "spellingLoc", [Spelling, this] { writeBareSourceLocation(Spelling); });
JOS.attributeObject("expansionLoc", [Expansion, Loc, this] {
- writeBareSourceLocation(Expansion, /*IsSpelling*/ false);
+ writeBareSourceLocation(Expansion);
// If there is a macro expansion, add extra information if the interesting
// bit is the macro arg expansion.
if (SM.isMacroArgExpansion(Loc))
JOS.attribute("isMacroArgExpansion", true);
});
} else
- writeBareSourceLocation(Spelling, /*IsSpelling*/ true);
+ writeBareSourceLocation(Spelling);
}
void JSONNodeDumper::writeSourceRange(SourceRange R) {
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 59d9459..0640fed 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -105,6 +105,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
return static_cast<const OMPFilterClause *>(C);
case OMPC_ompx_dyn_cgroup_mem:
return static_cast<const OMPXDynCGroupMemClause *>(C);
+ case OMPC_dyn_groupprivate:
+ return static_cast<const OMPDynGroupprivateClause *>(C);
case OMPC_message:
return static_cast<const OMPMessageClause *>(C);
case OMPC_default:
@@ -2857,6 +2859,24 @@ void OMPClausePrinter::VisitOMPXDynCGroupMemClause(
OS << ")";
}
+void OMPClausePrinter::VisitOMPDynGroupprivateClause(
+ OMPDynGroupprivateClause *Node) {
+ OS << "dyn_groupprivate(";
+ if (Node->getDynGroupprivateModifier() != OMPC_DYN_GROUPPRIVATE_unknown) {
+ OS << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate,
+ Node->getDynGroupprivateModifier());
+ if (Node->getDynGroupprivateFallbackModifier() !=
+ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown) {
+ OS << ", ";
+ OS << getOpenMPSimpleClauseTypeName(
+ OMPC_dyn_groupprivate, Node->getDynGroupprivateFallbackModifier());
+ }
+ OS << ": ";
+ }
+ Node->getSize()->printPretty(OS, nullptr, Policy, 0);
+ OS << ')';
+}
+
void OMPClausePrinter::VisitOMPDoacrossClause(OMPDoacrossClause *Node) {
OS << "doacross(";
OpenMPDoacrossClauseModifier DepType = Node->getDependenceType();
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index c909e1b..4a8c638 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -968,6 +968,12 @@ void OMPClauseProfiler::VisitOMPXDynCGroupMemClause(
if (Expr *Size = C->getSize())
Profiler->VisitStmt(Size);
}
+void OMPClauseProfiler::VisitOMPDynGroupprivateClause(
+ const OMPDynGroupprivateClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ if (auto *Size = C->getSize())
+ Profiler->VisitStmt(Size);
+}
void OMPClauseProfiler::VisitOMPDoacrossClause(const OMPDoacrossClause *C) {
VisitOMPClauseList(C);
}
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 549d720..41aebdb 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -2461,7 +2461,6 @@ void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
break;
case VarDecl::ParenListInit:
OS << " parenlistinit";
- break;
}
}
if (D->needsDestruction(D->getASTContext()))
@@ -2469,19 +2468,6 @@ void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
if (D->isParameterPack())
OS << " pack";
- VarDecl::DefinitionKind K = D->isThisDeclarationADefinition();
- switch (K) {
- case VarDecl::DefinitionKind::DeclarationOnly:
- OS << " declaration";
- break;
- case VarDecl::DefinitionKind::Definition:
- OS << " definition";
- break;
- case VarDecl::DefinitionKind::TentativeDefinition:
- OS << " tentative definition";
- break;
- }
-
if (const auto *Instance = D->getTemplateInstantiationPattern()) {
OS << " instantiated_from";
dumpPointer(Instance);
diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp
index 54c30c0..2f40c7e 100644
--- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp
+++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp
@@ -238,10 +238,12 @@ const auto isMoveOnly = [] {
};
template <class T> struct NodeID;
-template <> struct NodeID<Expr> { static constexpr StringRef value = "expr"; };
-template <> struct NodeID<Decl> { static constexpr StringRef value = "decl"; };
-constexpr StringRef NodeID<Expr>::value;
-constexpr StringRef NodeID<Decl>::value;
+template <> struct NodeID<Expr> {
+ static constexpr StringRef value = "expr";
+};
+template <> struct NodeID<Decl> {
+ static constexpr StringRef value = "decl";
+};
template <class T,
class F = const Stmt *(ExprMutationAnalyzer::Analyzer::*)(const T *)>
diff --git a/clang/lib/Analysis/LifetimeSafety/Dataflow.h b/clang/lib/Analysis/LifetimeSafety/Dataflow.h
index 2f7bcb6..de821bb 100644
--- a/clang/lib/Analysis/LifetimeSafety/Dataflow.h
+++ b/clang/lib/Analysis/LifetimeSafety/Dataflow.h
@@ -67,10 +67,10 @@ private:
llvm::DenseMap<const CFGBlock *, Lattice> InStates;
/// The dataflow state after a basic block is processed.
llvm::DenseMap<const CFGBlock *, Lattice> OutStates;
- /// The dataflow state at a Program Point.
+ /// Dataflow state at each program point, indexed by Fact ID.
/// In a forward analysis, this is the state after the Fact at that point has
/// been applied, while in a backward analysis, it is the state before.
- llvm::DenseMap<ProgramPoint, Lattice> PerPointStates;
+ llvm::SmallVector<Lattice> PointToState;
static constexpr bool isForward() { return Dir == Direction::Forward; }
@@ -86,6 +86,8 @@ public:
Derived &D = static_cast<Derived &>(*this);
llvm::TimeTraceScope Time(D.getAnalysisName());
+ PointToState.resize(FactMgr.getNumFacts());
+
using Worklist =
std::conditional_t<Dir == Direction::Forward, ForwardDataflowWorklist,
BackwardDataflowWorklist>;
@@ -116,7 +118,9 @@ public:
}
protected:
- Lattice getState(ProgramPoint P) const { return PerPointStates.lookup(P); }
+ Lattice getState(ProgramPoint P) const {
+ return PointToState[P->getID().Value];
+ }
std::optional<Lattice> getInState(const CFGBlock *B) const {
auto It = InStates.find(B);
@@ -144,12 +148,12 @@ private:
if constexpr (isForward()) {
for (const Fact *F : Facts) {
State = transferFact(State, F);
- PerPointStates[F] = State;
+ PointToState[F->getID().Value] = State;
}
} else {
for (const Fact *F : llvm::reverse(Facts)) {
// In backward analysis, capture the state before applying the fact.
- PerPointStates[F] = State;
+ PointToState[F->getID().Value] = State;
State = transferFact(State, F);
}
}
diff --git a/clang/lib/Analysis/LifetimeSafety/Facts.cpp b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
index 1aea64f..4a4172f 100644
--- a/clang/lib/Analysis/LifetimeSafety/Facts.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
@@ -53,7 +53,7 @@ void ReturnOfOriginFact::dump(llvm::raw_ostream &OS, const LoanManager &,
void UseFact::dump(llvm::raw_ostream &OS, const LoanManager &,
const OriginManager &OM) const {
OS << "Use (";
- OM.dump(getUsedOrigin(OM), OS);
+ OM.dump(getUsedOrigin(), OS);
OS << ", " << (isWritten() ? "Write" : "Read") << ")\n";
}
@@ -64,8 +64,8 @@ void TestPointFact::dump(llvm::raw_ostream &OS, const LoanManager &,
llvm::StringMap<ProgramPoint> FactManager::getTestPoints() const {
llvm::StringMap<ProgramPoint> AnnotationToPointMap;
- for (const CFGBlock *Block : BlockToFactsMap.keys()) {
- for (const Fact *F : getFacts(Block)) {
+ for (const auto &BlockFacts : BlockToFacts) {
+ for (const Fact *F : BlockFacts) {
if (const auto *TPF = F->getAs<TestPointFact>()) {
StringRef PointName = TPF->getAnnotation();
assert(AnnotationToPointMap.find(PointName) ==
@@ -88,12 +88,9 @@ void FactManager::dump(const CFG &Cfg, AnalysisDeclContext &AC) const {
// Print blocks in the order as they appear in code for a stable ordering.
for (const CFGBlock *B : *AC.getAnalysis<PostOrderCFGView>()) {
llvm::dbgs() << " Block B" << B->getBlockID() << ":\n";
- auto It = BlockToFactsMap.find(B);
- if (It != BlockToFactsMap.end()) {
- for (const Fact *F : It->second) {
- llvm::dbgs() << " ";
- F->dump(llvm::dbgs(), LoanMgr, OriginMgr);
- }
+ for (const Fact *F : getFacts(B)) {
+ llvm::dbgs() << " ";
+ F->dump(llvm::dbgs(), LoanMgr, OriginMgr);
}
llvm::dbgs() << " End of Block\n";
}
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 9b68de1..bec8e1d 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -333,7 +333,7 @@ void FactsGenerator::handleAssignment(const Expr *LHSExpr,
// (e.g. on the left-hand side of an assignment).
void FactsGenerator::handleUse(const DeclRefExpr *DRE) {
if (isPointerType(DRE->getType())) {
- UseFact *UF = FactMgr.createFact<UseFact>(DRE);
+ UseFact *UF = FactMgr.createFact<UseFact>(DRE, FactMgr.getOriginMgr());
CurrentBlockFacts.push_back(UF);
assert(!UseFacts.contains(DRE));
UseFacts[DRE] = UF;
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index 00c7ed90..a51ba42 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -41,6 +41,7 @@ void LifetimeSafetyAnalysis::run() {
const CFG &Cfg = *AC.getCFG();
DEBUG_WITH_TYPE("PrintCFG", Cfg.dump(AC.getASTContext().getLangOpts(),
/*ShowColors=*/true));
+ FactMgr.init(Cfg);
FactsGenerator FactGen(FactMgr, AC);
FactGen.run();
diff --git a/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp b/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
index cddb3f3c..59f594e 100644
--- a/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
@@ -111,7 +111,7 @@ public:
/// dominates this program point. A write operation kills the liveness of
/// the origin since it overwrites the value.
Lattice transfer(Lattice In, const UseFact &UF) {
- OriginID OID = UF.getUsedOrigin(FactMgr.getOriginMgr());
+ OriginID OID = UF.getUsedOrigin();
// Write kills liveness.
if (UF.isWritten())
return Lattice(Factory.remove(In.LiveOrigins, OID));
diff --git a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
index 387097e..0e6c194 100644
--- a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
@@ -5,36 +5,114 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h"
-#include "Dataflow.h"
+#include <cassert>
#include <memory>
+#include "Dataflow.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/Loans.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
+#include "clang/Analysis/Analyses/LifetimeSafety/Utils.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/TimeProfiler.h"
+#include "llvm/Support/raw_ostream.h"
+
namespace clang::lifetimes::internal {
+
+// Prepass to find persistent origins. An origin is persistent if it is
+// referenced in more than one basic block.
+static llvm::BitVector computePersistentOrigins(const FactManager &FactMgr,
+ const CFG &C) {
+ llvm::TimeTraceScope("ComputePersistentOrigins");
+ unsigned NumOrigins = FactMgr.getOriginMgr().getNumOrigins();
+ llvm::BitVector PersistentOrigins(NumOrigins);
+
+ llvm::SmallVector<const CFGBlock *> OriginToFirstSeenBlock(NumOrigins,
+ nullptr);
+ for (const CFGBlock *B : C) {
+ for (const Fact *F : FactMgr.getFacts(B)) {
+ auto CheckOrigin = [&](OriginID OID) {
+ if (PersistentOrigins.test(OID.Value))
+ return;
+ auto &FirstSeenBlock = OriginToFirstSeenBlock[OID.Value];
+ if (FirstSeenBlock == nullptr)
+ FirstSeenBlock = B;
+ if (FirstSeenBlock != B) {
+ // We saw this origin in more than one block.
+ PersistentOrigins.set(OID.Value);
+ }
+ };
+
+ switch (F->getKind()) {
+ case Fact::Kind::Issue:
+ CheckOrigin(F->getAs<IssueFact>()->getOriginID());
+ break;
+ case Fact::Kind::OriginFlow: {
+ const auto *OF = F->getAs<OriginFlowFact>();
+ CheckOrigin(OF->getDestOriginID());
+ CheckOrigin(OF->getSrcOriginID());
+ break;
+ }
+ case Fact::Kind::ReturnOfOrigin:
+ CheckOrigin(F->getAs<ReturnOfOriginFact>()->getReturnedOriginID());
+ break;
+ case Fact::Kind::Use:
+ CheckOrigin(F->getAs<UseFact>()->getUsedOrigin());
+ break;
+ case Fact::Kind::Expire:
+ case Fact::Kind::TestPoint:
+ break;
+ }
+ }
+ }
+ return PersistentOrigins;
+}
+
namespace {
+
/// Represents the dataflow lattice for loan propagation.
///
/// This lattice tracks which loans each origin may hold at a given program
/// point.The lattice has a finite height: An origin's loan set is bounded by
/// the total number of loans in the function.
-/// TODO(opt): To reduce the lattice size, propagate origins of declarations,
-/// not expressions, because expressions are not visible across blocks.
struct Lattice {
/// The map from an origin to the set of loans it contains.
- OriginLoanMap Origins = OriginLoanMap(nullptr);
-
- explicit Lattice(const OriginLoanMap &S) : Origins(S) {}
+ /// Origins that appear in multiple blocks. Participates in join operations.
+ OriginLoanMap PersistentOrigins = OriginLoanMap(nullptr);
+ /// Origins confined to a single block. Discarded at block boundaries.
+ OriginLoanMap BlockLocalOrigins = OriginLoanMap(nullptr);
+
+ explicit Lattice(const OriginLoanMap &Persistent,
+ const OriginLoanMap &BlockLocal)
+ : PersistentOrigins(Persistent), BlockLocalOrigins(BlockLocal) {}
Lattice() = default;
bool operator==(const Lattice &Other) const {
- return Origins == Other.Origins;
+ return PersistentOrigins == Other.PersistentOrigins &&
+ BlockLocalOrigins == Other.BlockLocalOrigins;
}
bool operator!=(const Lattice &Other) const { return !(*this == Other); }
void dump(llvm::raw_ostream &OS) const {
OS << "LoanPropagationLattice State:\n";
- if (Origins.isEmpty())
+ OS << " Persistent Origins:\n";
+ if (PersistentOrigins.isEmpty())
OS << " <empty>\n";
- for (const auto &Entry : Origins) {
+ for (const auto &Entry : PersistentOrigins) {
+ if (Entry.second.isEmpty())
+ OS << " Origin " << Entry.first << " contains no loans\n";
+ for (const LoanID &LID : Entry.second)
+ OS << " Origin " << Entry.first << " contains Loan " << LID << "\n";
+ }
+ OS << " Block-Local Origins:\n";
+ if (BlockLocalOrigins.isEmpty())
+ OS << " <empty>\n";
+ for (const auto &Entry : BlockLocalOrigins) {
if (Entry.second.isEmpty())
OS << " Origin " << Entry.first << " contains no loans\n";
for (const LoanID &LID : Entry.second)
@@ -50,7 +128,8 @@ public:
OriginLoanMap::Factory &OriginLoanMapFactory,
LoanSet::Factory &LoanSetFactory)
: DataflowAnalysis(C, AC, F), OriginLoanMapFactory(OriginLoanMapFactory),
- LoanSetFactory(LoanSetFactory) {}
+ LoanSetFactory(LoanSetFactory),
+ PersistentOrigins(computePersistentOrigins(F, C)) {}
using Base::transfer;
@@ -59,10 +138,10 @@ public:
Lattice getInitialState() { return Lattice{}; }
/// Merges two lattices by taking the union of loans for each origin.
- // TODO(opt): Keep the state small by removing origins which become dead.
+ /// Only persistent origins are joined; block-local origins are discarded.
Lattice join(Lattice A, Lattice B) {
OriginLoanMap JoinedOrigins = utils::join(
- A.Origins, B.Origins, OriginLoanMapFactory,
+ A.PersistentOrigins, B.PersistentOrigins, OriginLoanMapFactory,
[&](const LoanSet *S1, const LoanSet *S2) {
assert((S1 || S2) && "unexpectedly merging 2 empty sets");
if (!S1)
@@ -74,16 +153,15 @@ public:
// Asymmetric join is a performance win. For origins present only on one
// branch, the loan set can be carried over as-is.
utils::JoinKind::Asymmetric);
- return Lattice(JoinedOrigins);
+ return Lattice(JoinedOrigins, OriginLoanMapFactory.getEmptyMap());
}
/// A new loan is issued to the origin. Old loans are erased.
Lattice transfer(Lattice In, const IssueFact &F) {
OriginID OID = F.getOriginID();
LoanID LID = F.getLoanID();
- return Lattice(OriginLoanMapFactory.add(
- In.Origins, OID,
- LoanSetFactory.add(LoanSetFactory.getEmptySet(), LID)));
+ LoanSet NewLoans = LoanSetFactory.add(LoanSetFactory.getEmptySet(), LID);
+ return setLoans(In, OID, NewLoans);
}
/// A flow from source to destination. If `KillDest` is true, this replaces
@@ -98,7 +176,7 @@ public:
LoanSet SrcLoans = getLoans(In, SrcOID);
LoanSet MergedLoans = utils::join(DestLoans, SrcLoans, LoanSetFactory);
- return Lattice(OriginLoanMapFactory.add(In.Origins, DestOID, MergedLoans));
+ return setLoans(In, DestOID, MergedLoans);
}
LoanSet getLoans(OriginID OID, ProgramPoint P) const {
@@ -106,14 +184,33 @@ public:
}
private:
+ /// Returns true if the origin is persistent (referenced in multiple blocks).
+ bool isPersistent(OriginID OID) const {
+ return PersistentOrigins.test(OID.Value);
+ }
+
+ Lattice setLoans(Lattice L, OriginID OID, LoanSet Loans) {
+ if (isPersistent(OID))
+ return Lattice(OriginLoanMapFactory.add(L.PersistentOrigins, OID, Loans),
+ L.BlockLocalOrigins);
+ return Lattice(L.PersistentOrigins,
+ OriginLoanMapFactory.add(L.BlockLocalOrigins, OID, Loans));
+ }
+
LoanSet getLoans(Lattice L, OriginID OID) const {
- if (auto *Loans = L.Origins.lookup(OID))
+ const OriginLoanMap *Map =
+ isPersistent(OID) ? &L.PersistentOrigins : &L.BlockLocalOrigins;
+ if (auto *Loans = Map->lookup(OID))
return *Loans;
return LoanSetFactory.getEmptySet();
}
OriginLoanMap::Factory &OriginLoanMapFactory;
LoanSet::Factory &LoanSetFactory;
+ /// Boolean vector indexed by origin ID. If true, the origin appears in
+ /// multiple basic blocks and must participate in join operations. If false,
+ /// the origin is block-local and can be discarded at block boundaries.
+ llvm::BitVector PersistentOrigins;
};
} // namespace
diff --git a/clang/lib/Basic/BuiltinTargetFeatures.h b/clang/lib/Basic/BuiltinTargetFeatures.h
index 9754acd..bf227a1 100644
--- a/clang/lib/Basic/BuiltinTargetFeatures.h
+++ b/clang/lib/Basic/BuiltinTargetFeatures.h
@@ -20,7 +20,7 @@ using llvm::StringRef;
namespace clang {
namespace Builtin {
/// TargetFeatures - This class is used to check whether the builtin function
-/// has the required tagert specific features. It is able to support the
+/// has the required target specific features. It is able to support the
/// combination of ','(and), '|'(or), and '()'. By default, the priority of
/// ',' is higher than that of '|' .
/// E.g:
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 3d41f2d..8e60fc2 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -196,6 +196,16 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
return OMPC_GRAINSIZE_unknown;
return Type;
}
+ case OMPC_dyn_groupprivate: {
+ return llvm::StringSwitch<unsigned>(Str)
+#define OPENMP_DYN_GROUPPRIVATE_MODIFIER(Name) \
+ .Case(#Name, OMPC_DYN_GROUPPRIVATE_##Name)
+#define OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(Name) \
+ .Case(#Name, OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name) \
+ .Case("fallback(" #Name ")", OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_DYN_GROUPPRIVATE_unknown);
+ }
case OMPC_num_tasks: {
unsigned Type = llvm::StringSwitch<unsigned>(Str)
#define OPENMP_NUMTASKS_MODIFIER(Name) .Case(#Name, OMPC_NUMTASKS_##Name)
@@ -544,6 +554,20 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'grainsize' clause modifier");
+ case OMPC_dyn_groupprivate:
+ switch (Type) {
+ case OMPC_DYN_GROUPPRIVATE_unknown:
+ case OMPC_DYN_GROUPPRIVATE_FALLBACK_last:
+ return "unknown";
+#define OPENMP_DYN_GROUPPRIVATE_MODIFIER(Name) \
+ case OMPC_DYN_GROUPPRIVATE_##Name: \
+ return #Name;
+#define OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(Name) \
+ case OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name: \
+ return "fallback(" #Name ")";
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'dyn_groupprivate' clause modifier");
case OMPC_num_tasks:
switch (Type) {
case OMPC_NUMTASKS_unknown:
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
index 1eb7199..7bb8c21 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
@@ -66,7 +66,7 @@ static mlir::LogicalResult emitStmtWithResult(CIRGenFunction &cgf,
mlir::LogicalResult CIRGenFunction::emitCompoundStmtWithoutScope(
const CompoundStmt &s, Address *lastValue, AggValueSlot slot) {
mlir::LogicalResult result = mlir::success();
- const Stmt *exprResult = s.getStmtExprResult();
+ const Stmt *exprResult = s.body_back();
assert((!lastValue || (lastValue && exprResult)) &&
"If lastValue is not null then the CompoundStmt must have a "
"StmtExprResult");
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index bbcee34..0a2ea41 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -1211,14 +1211,10 @@ llvm::Value *CodeGenFunction::emitCountedByPointerSize(
getContext().getTypeSizeInChars(ElementTy->getPointeeType());
if (ElementSize.isZero()) {
- // This might be a __sized_by on a 'void *', which counts bytes, not
- // elements.
- auto *CAT = ElementTy->getAs<CountAttributedType>();
- if (!CAT || (CAT->getKind() != CountAttributedType::SizedBy &&
- CAT->getKind() != CountAttributedType::SizedByOrNull))
- // Okay, not sure what it is now.
- // FIXME: Should this be an assert?
- return std::optional<CharUnits>();
+ // This might be a __sized_by (or __counted_by) on a
+ // 'void *', which counts bytes, not elements.
+ [[maybe_unused]] auto *CAT = ElementTy->getAs<CountAttributedType>();
+ assert(CAT && "must have an CountAttributedType");
ElementSize = CharUnits::One();
}
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index fdc1a11..36be329 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -582,48 +582,45 @@ CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S,
bool GetLast,
AggValueSlot AggSlot) {
- const Stmt *ExprResult = S.getStmtExprResult();
- assert((!GetLast || (GetLast && ExprResult)) &&
- "If GetLast is true then the CompoundStmt must have a StmtExprResult");
+ for (CompoundStmt::const_body_iterator I = S.body_begin(),
+ E = S.body_end() - GetLast;
+ I != E; ++I)
+ EmitStmt(*I);
Address RetAlloca = Address::invalid();
-
- for (auto *CurStmt : S.body()) {
- if (GetLast && ExprResult == CurStmt) {
- // We have to special case labels here. They are statements, but when put
- // at the end of a statement expression, they yield the value of their
- // subexpression. Handle this by walking through all labels we encounter,
- // emitting them before we evaluate the subexpr.
- // Similar issues arise for attributed statements.
- while (!isa<Expr>(ExprResult)) {
- if (const auto *LS = dyn_cast<LabelStmt>(ExprResult)) {
- EmitLabel(LS->getDecl());
- ExprResult = LS->getSubStmt();
- } else if (const auto *AS = dyn_cast<AttributedStmt>(ExprResult)) {
- // FIXME: Update this if we ever have attributes that affect the
- // semantics of an expression.
- ExprResult = AS->getSubStmt();
- } else {
- llvm_unreachable("unknown value statement");
- }
+ if (GetLast) {
+ // We have to special case labels here. They are statements, but when put
+ // at the end of a statement expression, they yield the value of their
+ // subexpression. Handle this by walking through all labels we encounter,
+ // emitting them before we evaluate the subexpr.
+ // Similar issues arise for attributed statements.
+ const Stmt *LastStmt = S.body_back();
+ while (!isa<Expr>(LastStmt)) {
+ if (const auto *LS = dyn_cast<LabelStmt>(LastStmt)) {
+ EmitLabel(LS->getDecl());
+ LastStmt = LS->getSubStmt();
+ } else if (const auto *AS = dyn_cast<AttributedStmt>(LastStmt)) {
+ // FIXME: Update this if we ever have attributes that affect the
+ // semantics of an expression.
+ LastStmt = AS->getSubStmt();
+ } else {
+ llvm_unreachable("unknown value statement");
}
+ }
- EnsureInsertPoint();
+ EnsureInsertPoint();
- const Expr *E = cast<Expr>(ExprResult);
- QualType ExprTy = E->getType();
- if (hasAggregateEvaluationKind(ExprTy)) {
- EmitAggExpr(E, AggSlot);
- } else {
- // We can't return an RValue here because there might be cleanups at
- // the end of the StmtExpr. Because of that, we have to emit the result
- // here into a temporary alloca.
- RetAlloca = CreateMemTemp(ExprTy);
- EmitAnyExprToMem(E, RetAlloca, Qualifiers(),
- /*IsInit*/ false);
- }
+ const Expr *E = cast<Expr>(LastStmt);
+ QualType ExprTy = E->getType();
+ if (hasAggregateEvaluationKind(ExprTy)) {
+ EmitAggExpr(E, AggSlot);
} else {
- EmitStmt(CurStmt);
+ // We can't return an RValue here because there might be cleanups at
+ // the end of the StmtExpr. Because of that, we have to emit the result
+ // here into a temporary alloca.
+ RetAlloca = CreateMemTemp(ExprTy);
+ EmitAnyExprToMem(E, RetAlloca, Qualifiers(),
+ /*IsInit*/ false);
}
}
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 0fea57b..98d59b7 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2368,9 +2368,8 @@ static QualType GeneralizeTransparentUnion(QualType Ty) {
const RecordDecl *UD = UT->getDecl()->getDefinitionOrSelf();
if (!UD->hasAttr<TransparentUnionAttr>())
return Ty;
- for (const auto *it : UD->fields()) {
- return it->getType();
- }
+ if (!UD->fields().empty())
+ return UD->fields().begin()->getType();
return Ty;
}
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 8f09564..06d7380 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -58,9 +58,10 @@ enum PGOHashVersion : unsigned {
PGO_HASH_V1,
PGO_HASH_V2,
PGO_HASH_V3,
+ PGO_HASH_V4,
// Keep this set to the latest hash version.
- PGO_HASH_LATEST = PGO_HASH_V3
+ PGO_HASH_LATEST = PGO_HASH_V4
};
namespace {
@@ -152,7 +153,9 @@ static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
return PGO_HASH_V1;
if (PGOReader->getVersion() <= 5)
return PGO_HASH_V2;
- return PGO_HASH_V3;
+ if (PGOReader->getVersion() <= 12)
+ return PGO_HASH_V3;
+ return PGO_HASH_V4;
}
/// A RecursiveASTVisitor that fills a map of statements to PGO counters.
@@ -1099,6 +1102,8 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
NumRegionCounters = Walker.NextCounter;
FunctionHash = Walker.Hash.finalize();
+ if (HashVersion >= PGO_HASH_V4)
+ FunctionHash &= llvm::NamedInstrProfRecord::FUNC_HASH_MASK;
}
bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) {
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index 15fa78d..d4b0b81 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -590,6 +590,7 @@ struct ARMVectorIntrinsicInfo {
Intrinsic::LLVMIntrinsic, Intrinsic::AltLLVMIntrinsic, \
TypeModifier }
+// clang-format off
static const ARMVectorIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP1(__a32_vcvt_bf16_f32, arm_neon_vcvtfp2bf, 0),
NEONMAP0(splat_lane_v),
@@ -1217,35 +1218,55 @@ static const ARMVectorIntrinsicInfo AArch64SISDIntrinsicMap[] = {
NEONMAP1(vcales_f32, aarch64_neon_facge, AddRetType | Add1ArgType),
NEONMAP1(vcaltd_f64, aarch64_neon_facgt, AddRetType | Add1ArgType),
NEONMAP1(vcalts_f32, aarch64_neon_facgt, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtad_s32_f64, aarch64_neon_fcvtas, AddRetType | Add1ArgType),
NEONMAP1(vcvtad_s64_f64, aarch64_neon_fcvtas, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtad_u32_f64, aarch64_neon_fcvtau, AddRetType | Add1ArgType),
NEONMAP1(vcvtad_u64_f64, aarch64_neon_fcvtau, AddRetType | Add1ArgType),
NEONMAP1(vcvtas_s32_f32, aarch64_neon_fcvtas, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtas_s64_f32, aarch64_neon_fcvtas, AddRetType | Add1ArgType),
NEONMAP1(vcvtas_u32_f32, aarch64_neon_fcvtau, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtas_u64_f32, aarch64_neon_fcvtau, AddRetType | Add1ArgType),
NEONMAP1(vcvtd_n_f64_s64, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType),
NEONMAP1(vcvtd_n_f64_u64, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType),
NEONMAP1(vcvtd_n_s64_f64, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType),
NEONMAP1(vcvtd_n_u64_f64, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtd_s32_f64, aarch64_neon_fcvtzs, AddRetType | Add1ArgType),
NEONMAP1(vcvtd_s64_f64, aarch64_neon_fcvtzs, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtd_u32_f64, aarch64_neon_fcvtzu, AddRetType | Add1ArgType),
NEONMAP1(vcvtd_u64_f64, aarch64_neon_fcvtzu, AddRetType | Add1ArgType),
NEONMAP0(vcvth_bf16_f32),
+ NEONMAP1(vcvtmd_s32_f64, aarch64_neon_fcvtms, AddRetType | Add1ArgType),
NEONMAP1(vcvtmd_s64_f64, aarch64_neon_fcvtms, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtmd_u32_f64, aarch64_neon_fcvtmu, AddRetType | Add1ArgType),
NEONMAP1(vcvtmd_u64_f64, aarch64_neon_fcvtmu, AddRetType | Add1ArgType),
NEONMAP1(vcvtms_s32_f32, aarch64_neon_fcvtms, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtms_s64_f32, aarch64_neon_fcvtms, AddRetType | Add1ArgType),
NEONMAP1(vcvtms_u32_f32, aarch64_neon_fcvtmu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtms_u64_f32, aarch64_neon_fcvtmu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtnd_s32_f64, aarch64_neon_fcvtns, AddRetType | Add1ArgType),
NEONMAP1(vcvtnd_s64_f64, aarch64_neon_fcvtns, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtnd_u32_f64, aarch64_neon_fcvtnu, AddRetType | Add1ArgType),
NEONMAP1(vcvtnd_u64_f64, aarch64_neon_fcvtnu, AddRetType | Add1ArgType),
NEONMAP1(vcvtns_s32_f32, aarch64_neon_fcvtns, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtns_s64_f32, aarch64_neon_fcvtns, AddRetType | Add1ArgType),
NEONMAP1(vcvtns_u32_f32, aarch64_neon_fcvtnu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtns_u64_f32, aarch64_neon_fcvtnu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtpd_s32_f64, aarch64_neon_fcvtps, AddRetType | Add1ArgType),
NEONMAP1(vcvtpd_s64_f64, aarch64_neon_fcvtps, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtpd_u32_f64, aarch64_neon_fcvtpu, AddRetType | Add1ArgType),
NEONMAP1(vcvtpd_u64_f64, aarch64_neon_fcvtpu, AddRetType | Add1ArgType),
NEONMAP1(vcvtps_s32_f32, aarch64_neon_fcvtps, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtps_s64_f32, aarch64_neon_fcvtps, AddRetType | Add1ArgType),
NEONMAP1(vcvtps_u32_f32, aarch64_neon_fcvtpu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvtps_u64_f32, aarch64_neon_fcvtpu, AddRetType | Add1ArgType),
NEONMAP1(vcvts_n_f32_s32, aarch64_neon_vcvtfxs2fp, AddRetType | Add1ArgType),
NEONMAP1(vcvts_n_f32_u32, aarch64_neon_vcvtfxu2fp, AddRetType | Add1ArgType),
NEONMAP1(vcvts_n_s32_f32, aarch64_neon_vcvtfp2fxs, AddRetType | Add1ArgType),
NEONMAP1(vcvts_n_u32_f32, aarch64_neon_vcvtfp2fxu, AddRetType | Add1ArgType),
NEONMAP1(vcvts_s32_f32, aarch64_neon_fcvtzs, AddRetType | Add1ArgType),
+ NEONMAP1(vcvts_s64_f32, aarch64_neon_fcvtzs, AddRetType | Add1ArgType),
NEONMAP1(vcvts_u32_f32, aarch64_neon_fcvtzu, AddRetType | Add1ArgType),
+ NEONMAP1(vcvts_u64_f32, aarch64_neon_fcvtzu, AddRetType | Add1ArgType),
NEONMAP1(vcvtxd_f32_f64, aarch64_sisd_fcvtxn, 0),
NEONMAP1(vmaxnmv_f32, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType),
NEONMAP1(vmaxnmvq_f32, aarch64_neon_fmaxnmv, AddRetType | Add1ArgType),
@@ -1446,6 +1467,7 @@ static const ARMVectorIntrinsicInfo AArch64SISDIntrinsicMap[] = {
NEONMAP1(vrsqrteh_f16, aarch64_neon_frsqrte, Add1ArgType),
NEONMAP1(vrsqrtsh_f16, aarch64_neon_frsqrts, Add1ArgType),
};
+// clang-format on
// Some intrinsics are equivalent for codegen.
static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
@@ -7624,6 +7646,16 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Int = Intrinsic::aarch64_neon_vluti4q_laneq_x2;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vluti4q_laneq_x2");
}
+ case NEON::BI__builtin_neon_vmmlaq_f16_mf8_fpm:
+ return EmitFP8NeonCall(Intrinsic::aarch64_neon_fmmla,
+ {llvm::FixedVectorType::get(HalfTy, 8),
+ llvm::FixedVectorType::get(Int8Ty, 16)},
+ Ops, E, "fmmla");
+ case NEON::BI__builtin_neon_vmmlaq_f32_mf8_fpm:
+ return EmitFP8NeonCall(Intrinsic::aarch64_neon_fmmla,
+ {llvm::FixedVectorType::get(FloatTy, 4),
+ llvm::FixedVectorType::get(Int8Ty, 16)},
+ Ops, E, "fmmla");
case NEON::BI__builtin_neon_vcvt1_low_bf16_mf8_fpm:
ExtractLow = true;
[[fallthrough]];
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index bb41a14..d42fcd8 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -422,6 +422,12 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
}
// Empty records:
+ // AAPCS64 does not say that empty records are ignored as arguments,
+ // but other compilers do so in certain situations, and we copy that behavior.
+ // Those situations are in fact language-mode-specific, which seems really
+ // unfortunate, but it's something we just have to accept. If this doesn't
+ // apply, just fall through to the standard argument-handling path.
+ // Darwin overrides the psABI here to ignore all empty records in all modes.
uint64_t Size = getContext().getTypeSize(Ty);
bool IsEmpty = isEmptyRecord(getContext(), Ty, true);
if (!Ty->isSVESizelessBuiltinType() && (IsEmpty || Size == 0)) {
@@ -434,9 +440,6 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
// behaviour here.
if (Size == 0)
return ABIArgInfo::getIgnore();
-
- // Otherwise, they are passed as if they have a size of 1 byte.
- return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
}
// Homogeneous Floating-point Aggregates (HFAs) need to be expanded.
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 654a382..1a243fe 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -22,6 +22,7 @@
#include "llvm/Support/Process.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/TargetParser.h"
#include <optional>
#include <system_error>
@@ -1095,9 +1096,21 @@ bool AMDGPUToolChain::shouldSkipSanitizeOption(
if (K != SanitizerKind::Address)
return true;
+ // Check 'xnack+' availability by default
+ llvm::StringRef Processor =
+ getProcessorFromTargetID(TC.getTriple(), TargetID);
+ auto ProcKind = TC.getTriple().isAMDGCN()
+ ? llvm::AMDGPU::parseArchAMDGCN(Processor)
+ : llvm::AMDGPU::parseArchR600(Processor);
+ auto Features = TC.getTriple().isAMDGCN()
+ ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind)
+ : llvm::AMDGPU::getArchAttrR600(ProcKind);
+ if (Features & llvm::AMDGPU::FEATURE_XNACK_ALWAYS)
+ return false;
+
+ // Look for the xnack feature in TargetID
llvm::StringMap<bool> FeatureMap;
auto OptionalGpuArch = parseTargetID(TC.getTriple(), TargetID, &FeatureMap);
-
assert(OptionalGpuArch && "Invalid Target ID");
(void)OptionalGpuArch;
auto Loc = FeatureMap.find("xnack");
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 30d3e52..e20963a 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -8266,6 +8266,30 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
<< "/kernel";
}
+ if (const Arg *A = Args.getLastArg(options::OPT__SLASH_vlen,
+ options::OPT__SLASH_vlen_EQ_256,
+ options::OPT__SLASH_vlen_EQ_512)) {
+ llvm::Triple::ArchType AT = getToolChain().getArch();
+ StringRef Default = AT == llvm::Triple::x86 ? "IA32" : "SSE2";
+ StringRef Arch = Args.getLastArgValue(options::OPT__SLASH_arch, Default);
+
+ if (A->getOption().matches(options::OPT__SLASH_vlen_EQ_512)) {
+ if (Arch == "AVX512F" || Arch == "AVX512")
+ CmdArgs.push_back("-mprefer-vector-width=512");
+ else
+ D.Diag(diag::warn_drv_argument_not_allowed_with)
+ << "/vlen=512" << std::string("/arch:").append(Arch);
+ }
+
+ if (A->getOption().matches(options::OPT__SLASH_vlen_EQ_256)) {
+ if (Arch == "AVX512F" || Arch == "AVX512")
+ CmdArgs.push_back("-mprefer-vector-width=256");
+ else if (Arch != "AVX" && Arch != "AVX2")
+ D.Diag(diag::warn_drv_argument_not_allowed_with)
+ << "/vlen=256" << std::string("/arch:").append(Arch);
+ }
+ }
+
Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
if (MostGeneralArg && BestCaseArg)
diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp
index 8d3fba7..5d7221b 100644
--- a/clang/lib/Driver/ToolChains/HLSL.cpp
+++ b/clang/lib/Driver/ToolChains/HLSL.cpp
@@ -567,3 +567,7 @@ bool HLSLToolChain::isLastJob(DerivedArgList &Args,
// output to the result file.
return true;
}
+
+void HLSLToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
+ CC1Args.push_back("-Wconversion");
+}
diff --git a/clang/lib/Driver/ToolChains/HLSL.h b/clang/lib/Driver/ToolChains/HLSL.h
index 3aed904..5bf385e 100644
--- a/clang/lib/Driver/ToolChains/HLSL.h
+++ b/clang/lib/Driver/ToolChains/HLSL.h
@@ -91,6 +91,8 @@ public:
// Set default DWARF version to 4 for DXIL uses version 4.
unsigned GetDefaultDwarfVersion() const override { return 4; }
+ void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
+
private:
mutable std::unique_ptr<tools::hlsl::Validator> Validator;
mutable std::unique_ptr<tools::hlsl::MetalConverter> MetalConverter;
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index dd14fcd..9bbb33c 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -876,27 +876,28 @@ template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
FormatStyle::TrailingCommentsAlignmentStyle &Value) {
IO.enumCase(Value, "Leave",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Leave, 0}));
+ {FormatStyle::TCAS_Leave, 0, true}));
IO.enumCase(Value, "Always",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Always, 0}));
+ {FormatStyle::TCAS_Always, 0, true}));
IO.enumCase(Value, "Never",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Never, 0}));
+ {FormatStyle::TCAS_Never, 0, true}));
// For backwards compatibility
IO.enumCase(Value, "true",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Always, 0}));
+ {FormatStyle::TCAS_Always, 0, true}));
IO.enumCase(Value, "false",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Never, 0}));
+ {FormatStyle::TCAS_Never, 0, true}));
}
static void mapping(IO &IO,
FormatStyle::TrailingCommentsAlignmentStyle &Value) {
+ IO.mapOptional("AlignPPAndNotPP", Value.AlignPPAndNotPP);
IO.mapOptional("Kind", Value.Kind);
IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);
}
@@ -1651,6 +1652,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignTrailingComments = {};
LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
+ LLVMStyle.AlignTrailingComments.AlignPPAndNotPP = true;
LLVMStyle.AllowAllArgumentsOnNextLine = true;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 406c77c..fece384 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -1007,9 +1007,13 @@ void WhitespaceManager::alignTrailingComments() {
return;
const int Size = Changes.size();
+ if (Size == 0)
+ return;
+
int MinColumn = 0;
int StartOfSequence = 0;
bool BreakBeforeNext = false;
+ bool IsInPP = Changes.front().Tok->Tok.is(tok::hash);
int NewLineThreshold = 1;
if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)
NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
@@ -1018,7 +1022,19 @@ void WhitespaceManager::alignTrailingComments() {
auto &C = Changes[I];
if (C.StartOfBlockComment)
continue;
- Newlines += C.NewlinesBefore;
+ if (C.NewlinesBefore != 0) {
+ Newlines += C.NewlinesBefore;
+ const bool WasInPP = std::exchange(
+ IsInPP, C.Tok->Tok.is(tok::hash) || (IsInPP && C.IsTrailingComment) ||
+ C.ContinuesPPDirective);
+ if (IsInPP != WasInPP && !Style.AlignTrailingComments.AlignPPAndNotPP) {
+ alignTrailingComments(StartOfSequence, I, MinColumn);
+ MinColumn = 0;
+ MaxColumn = INT_MAX;
+ StartOfSequence = I;
+ Newlines = 0;
+ }
+ }
if (!C.IsTrailingComment)
continue;
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 6b09f7f..8034ce9 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1058,7 +1058,9 @@ void CompilerInstance::printDiagnosticStats() {
if (!getLangOpts().CUDAIsDevice) {
OS << " when compiling for host";
} else {
- OS << " when compiling for " << getTargetOpts().CPU;
+ OS << " when compiling for "
+ << (!getTargetOpts().CPU.empty() ? getTargetOpts().CPU
+ : getTarget().getTriple().str());
}
}
OS << ".\n";
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index d7d56b8..3595bbc 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -1233,20 +1233,6 @@ void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() {
llvm::outs());
}
-void GetDependenciesByModuleNameAction::ExecuteAction() {
- CompilerInstance &CI = getCompilerInstance();
- Preprocessor &PP = CI.getPreprocessor();
- SourceManager &SM = PP.getSourceManager();
- FileID MainFileID = SM.getMainFileID();
- SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
- SmallVector<IdentifierLoc, 2> Path;
- IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
- Path.emplace_back(FileStart, ModuleID);
- auto ModResult = CI.loadModule(FileStart, Path, Module::Hidden, false);
- PPCallbacks *CB = PP.getPPCallbacks();
- CB->moduleImport(SourceLocation(), Path, ModResult);
-}
-
//===----------------------------------------------------------------------===//
// HLSL Specific Actions
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Headers/avx512bwintrin.h b/clang/lib/Headers/avx512bwintrin.h
index aab1f2b..203b600 100644
--- a/clang/lib/Headers/avx512bwintrin.h
+++ b/clang/lib/Headers/avx512bwintrin.h
@@ -92,69 +92,65 @@ _kxor_mask64(__mmask64 __A, __mmask64 __B) {
return (__mmask64)__builtin_ia32_kxordi((__mmask64)__A, (__mmask64)__B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_kortestc_mask32_u8(__mmask32 __A, __mmask32 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_kortestc_mask32_u8(__mmask32 __A, __mmask32 __B) {
return (unsigned char)__builtin_ia32_kortestcsi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_kortestz_mask32_u8(__mmask32 __A, __mmask32 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_kortestz_mask32_u8(__mmask32 __A, __mmask32 __B) {
return (unsigned char)__builtin_ia32_kortestzsi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_kortest_mask32_u8(__mmask32 __A, __mmask32 __B, unsigned char *__C) {
*__C = (unsigned char)__builtin_ia32_kortestcsi(__A, __B);
return (unsigned char)__builtin_ia32_kortestzsi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_kortestc_mask64_u8(__mmask64 __A, __mmask64 __B) {
return (unsigned char)__builtin_ia32_kortestcdi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_kortestz_mask64_u8(__mmask64 __A, __mmask64 __B) {
return (unsigned char)__builtin_ia32_kortestzdi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_kortest_mask64_u8(__mmask64 __A, __mmask64 __B, unsigned char *__C) {
*__C = (unsigned char)__builtin_ia32_kortestcdi(__A, __B);
return (unsigned char)__builtin_ia32_kortestzdi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_ktestc_mask32_u8(__mmask32 __A, __mmask32 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_ktestc_mask32_u8(__mmask32 __A, __mmask32 __B) {
return (unsigned char)__builtin_ia32_ktestcsi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_ktestz_mask32_u8(__mmask32 __A, __mmask32 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_ktestz_mask32_u8(__mmask32 __A, __mmask32 __B) {
return (unsigned char)__builtin_ia32_ktestzsi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_ktest_mask32_u8(__mmask32 __A, __mmask32 __B, unsigned char *__C) {
*__C = (unsigned char)__builtin_ia32_ktestcsi(__A, __B);
return (unsigned char)__builtin_ia32_ktestzsi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_ktestc_mask64_u8(__mmask64 __A, __mmask64 __B) {
return (unsigned char)__builtin_ia32_ktestcdi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_ktestz_mask64_u8(__mmask64 __A, __mmask64 __B) {
return (unsigned char)__builtin_ia32_ktestzdi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_ktest_mask64_u8(__mmask64 __A, __mmask64 __B, unsigned char *__C) {
*__C = (unsigned char)__builtin_ia32_ktestcdi(__A, __B);
return (unsigned char)__builtin_ia32_ktestzdi(__A, __B);
diff --git a/clang/lib/Headers/avx512cdintrin.h b/clang/lib/Headers/avx512cdintrin.h
index fb6dcb6..f9de207 100644
--- a/clang/lib/Headers/avx512cdintrin.h
+++ b/clang/lib/Headers/avx512cdintrin.h
@@ -17,8 +17,8 @@
/* Define the default attributes for the functions in this file. */
#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS \
- constexpr __attribute__((__always_inline__, __nodebug__, \
- __target__("avx512cd"), __min_vector_width__(512)))
+ __attribute__((__always_inline__, __nodebug__, __target__("avx512cd"), \
+ __min_vector_width__(512))) constexpr
#else
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __target__("avx512cd"), \
diff --git a/clang/lib/Headers/avx512dqintrin.h b/clang/lib/Headers/avx512dqintrin.h
index fef1a2d..29156e7 100644
--- a/clang/lib/Headers/avx512dqintrin.h
+++ b/clang/lib/Headers/avx512dqintrin.h
@@ -59,55 +59,49 @@ _kxor_mask8(__mmask8 __A, __mmask8 __B) {
return (__mmask8)__builtin_ia32_kxorqi((__mmask8)__A, (__mmask8)__B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_kortestc_mask8_u8(__mmask8 __A, __mmask8 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_kortestc_mask8_u8(__mmask8 __A, __mmask8 __B) {
return (unsigned char)__builtin_ia32_kortestcqi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_kortestz_mask8_u8(__mmask8 __A, __mmask8 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_kortestz_mask8_u8(__mmask8 __A, __mmask8 __B) {
return (unsigned char)__builtin_ia32_kortestzqi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_kortest_mask8_u8(__mmask8 __A, __mmask8 __B, unsigned char *__C) {
*__C = (unsigned char)__builtin_ia32_kortestcqi(__A, __B);
return (unsigned char)__builtin_ia32_kortestzqi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_ktestc_mask8_u8(__mmask8 __A, __mmask8 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_ktestc_mask8_u8(__mmask8 __A, __mmask8 __B) {
return (unsigned char)__builtin_ia32_ktestcqi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_ktestz_mask8_u8(__mmask8 __A, __mmask8 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_ktestz_mask8_u8(__mmask8 __A, __mmask8 __B) {
return (unsigned char)__builtin_ia32_ktestzqi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_ktest_mask8_u8(__mmask8 __A, __mmask8 __B, unsigned char *__C) {
*__C = (unsigned char)__builtin_ia32_ktestcqi(__A, __B);
return (unsigned char)__builtin_ia32_ktestzqi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_ktestc_mask16_u8(__mmask16 __A, __mmask16 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_ktestc_mask16_u8(__mmask16 __A, __mmask16 __B) {
return (unsigned char)__builtin_ia32_ktestchi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_ktestz_mask16_u8(__mmask16 __A, __mmask16 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_ktestz_mask16_u8(__mmask16 __A, __mmask16 __B) {
return (unsigned char)__builtin_ia32_ktestzhi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_ktest_mask16_u8(__mmask16 __A, __mmask16 __B, unsigned char *__C) {
*__C = (unsigned char)__builtin_ia32_ktestchi(__A, __B);
return (unsigned char)__builtin_ia32_ktestzhi(__A, __B);
diff --git a/clang/lib/Headers/avx512fintrin.h b/clang/lib/Headers/avx512fintrin.h
index 5fc0afa..997e960 100644
--- a/clang/lib/Headers/avx512fintrin.h
+++ b/clang/lib/Headers/avx512fintrin.h
@@ -8068,31 +8068,27 @@ _mm512_kor(__mmask16 __A, __mmask16 __B) {
return (__mmask16) __builtin_ia32_korhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ int __DEFAULT_FN_ATTRS
-_mm512_kortestc (__mmask16 __A, __mmask16 __B)
-{
+static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR
+_mm512_kortestc(__mmask16 __A, __mmask16 __B) {
return __builtin_ia32_kortestchi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ int __DEFAULT_FN_ATTRS
-_mm512_kortestz (__mmask16 __A, __mmask16 __B)
-{
+static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR
+_mm512_kortestz(__mmask16 __A, __mmask16 __B) {
return __builtin_ia32_kortestzhi ((__mmask16) __A, (__mmask16) __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_kortestc_mask16_u8(__mmask16 __A, __mmask16 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_kortestc_mask16_u8(__mmask16 __A, __mmask16 __B) {
return (unsigned char)__builtin_ia32_kortestchi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_kortestz_mask16_u8(__mmask16 __A, __mmask16 __B)
-{
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
+_kortestz_mask16_u8(__mmask16 __A, __mmask16 __B) {
return (unsigned char)__builtin_ia32_kortestzhi(__A, __B);
}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
+static __inline__ unsigned char __DEFAULT_FN_ATTRS_CONSTEXPR
_kortest_mask16_u8(__mmask16 __A, __mmask16 __B, unsigned char *__C) {
*__C = (unsigned char)__builtin_ia32_kortestchi(__A, __B);
return (unsigned char)__builtin_ia32_kortestzhi(__A, __B);
diff --git a/clang/lib/Headers/avx512vlcdintrin.h b/clang/lib/Headers/avx512vlcdintrin.h
index 7719680f..df66e1d 100644
--- a/clang/lib/Headers/avx512vlcdintrin.h
+++ b/clang/lib/Headers/avx512vlcdintrin.h
@@ -16,13 +16,13 @@
/* Define the default attributes for the functions in this file. */
#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS128 \
- constexpr __attribute__((__always_inline__, __nodebug__, \
- __target__("avx512vl,avx512cd"), \
- __min_vector_width__(128)))
+ __attribute__((__always_inline__, __nodebug__, \
+ __target__("avx512vl,avx512cd"), \
+ __min_vector_width__(128))) constexpr
#define __DEFAULT_FN_ATTRS256 \
- constexpr __attribute__((__always_inline__, __nodebug__, \
- __target__("avx512vl,avx512cd"), \
- __min_vector_width__(256)))
+ __attribute__((__always_inline__, __nodebug__, \
+ __target__("avx512vl,avx512cd"), \
+ __min_vector_width__(256))) constexpr
#else
#define __DEFAULT_FN_ATTRS128 \
__attribute__((__always_inline__, __nodebug__, \
diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
index 208776e..2e2703d 100644
--- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
@@ -1074,78 +1074,6 @@ _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_f16tof32)
float4 f16tof32(uint4);
//===----------------------------------------------------------------------===//
-// firstbithigh builtins
-//===----------------------------------------------------------------------===//
-
-/// \fn T firstbithigh(T Val)
-/// \brief Returns the location of the first set bit starting from the highest
-/// order bit and working downward, per component.
-/// \param Val the input value.
-
-#ifdef __HLSL_ENABLE_16_BIT
-_HLSL_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint firstbithigh(int16_t);
-_HLSL_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint2 firstbithigh(int16_t2);
-_HLSL_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint3 firstbithigh(int16_t3);
-_HLSL_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint4 firstbithigh(int16_t4);
-_HLSL_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint firstbithigh(uint16_t);
-_HLSL_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint2 firstbithigh(uint16_t2);
-_HLSL_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint3 firstbithigh(uint16_t3);
-_HLSL_AVAILABILITY(shadermodel, 6.2)
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint4 firstbithigh(uint16_t4);
-#endif
-
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint firstbithigh(int);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint2 firstbithigh(int2);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint3 firstbithigh(int3);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint4 firstbithigh(int4);
-
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint firstbithigh(uint);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint2 firstbithigh(uint2);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint3 firstbithigh(uint3);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint4 firstbithigh(uint4);
-
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint firstbithigh(int64_t);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint2 firstbithigh(int64_t2);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint3 firstbithigh(int64_t3);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint4 firstbithigh(int64_t4);
-
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint firstbithigh(uint64_t);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint2 firstbithigh(uint64_t2);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint3 firstbithigh(uint64_t3);
-_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_firstbithigh)
-uint4 firstbithigh(uint64_t4);
-
-//===----------------------------------------------------------------------===//
// firstbitlow builtins
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
index c877234..3d8fe7e 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
@@ -148,6 +148,18 @@ template <typename T> constexpr T ldexp_impl(T X, T Exp) {
return exp2(Exp) * X;
}
+template <typename K, typename T, int BitWidth>
+constexpr K firstbithigh_impl(T X) {
+ K FBH = __builtin_hlsl_elementwise_firstbithigh(X);
+#if defined(__DIRECTX__)
+ // The firstbithigh DXIL ops count bits from the wrong side, so we need to
+ // invert it for DirectX.
+ K Inversion = (BitWidth - 1) - FBH;
+ FBH = select(FBH == -1, FBH, Inversion);
+#endif
+ return FBH;
+}
+
} // namespace __detail
} // namespace hlsl
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 5ba5bfb..33ed143 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -262,6 +262,67 @@ faceforward(__detail::HLSL_FIXED_VECTOR<float, L> N,
}
//===----------------------------------------------------------------------===//
+// firstbithigh builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T firstbithigh(T Val)
+/// \brief Returns the location of the first set bit starting from the lowest
+/// order bit and working upward, per component.
+/// \param Val the input value.
+
+#ifdef __HLSL_ENABLE_16_BIT
+
+template <typename T>
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+const inline __detail::enable_if_t<__detail::is_same<int16_t, T>::value ||
+ __detail::is_same<uint16_t, T>::value,
+ uint> firstbithigh(T X) {
+ return __detail::firstbithigh_impl<uint, T, 16>(X);
+}
+
+template <typename T, int N>
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+const
+ inline __detail::enable_if_t<__detail::is_same<int16_t, T>::value ||
+ __detail::is_same<uint16_t, T>::value,
+ vector<uint, N>> firstbithigh(vector<T, N> X) {
+ return __detail::firstbithigh_impl<vector<uint, N>, vector<T, N>, 16>(X);
+}
+
+#endif
+
+template <typename T>
+const inline __detail::enable_if_t<
+ __detail::is_same<int, T>::value || __detail::is_same<uint, T>::value, uint>
+firstbithigh(T X) {
+ return __detail::firstbithigh_impl<uint, T, 32>(X);
+}
+
+template <typename T, int N>
+const inline __detail::enable_if_t<__detail::is_same<int, T>::value ||
+ __detail::is_same<uint, T>::value,
+ vector<uint, N>>
+firstbithigh(vector<T, N> X) {
+ return __detail::firstbithigh_impl<vector<uint, N>, vector<T, N>, 32>(X);
+}
+
+template <typename T>
+const inline __detail::enable_if_t<__detail::is_same<int64_t, T>::value ||
+ __detail::is_same<uint64_t, T>::value,
+ uint>
+firstbithigh(T X) {
+ return __detail::firstbithigh_impl<uint, T, 64>(X);
+}
+
+template <typename T, int N>
+const inline __detail::enable_if_t<__detail::is_same<int64_t, T>::value ||
+ __detail::is_same<uint64_t, T>::value,
+ vector<uint, N>>
+firstbithigh(vector<T, N> X) {
+ return __detail::firstbithigh_impl<vector<uint, N>, vector<T, N>, 64>(X);
+}
+
+//===----------------------------------------------------------------------===//
// fmod builtins
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Headers/llvm_libc_wrappers/stdlib.h b/clang/lib/Headers/llvm_libc_wrappers/stdlib.h
index 1da22abd0..d79e7fa 100644
--- a/clang/lib/Headers/llvm_libc_wrappers/stdlib.h
+++ b/clang/lib/Headers/llvm_libc_wrappers/stdlib.h
@@ -34,13 +34,13 @@ _Static_assert(__builtin_offsetof(div_t, quot) == 0, "ABI mismatch!");
_Static_assert(__builtin_offsetof(ldiv_t, quot) == 0, "ABI mismatch!");
_Static_assert(__builtin_offsetof(lldiv_t, quot) == 0, "ABI mismatch!");
-#if defined(__GLIBC__) && __cplusplus >= 201703L
+#if defined(__GLIBC__) && __cplusplus >= 201103L
#define at_quick_exit atexit
#endif
#include <llvm-libc-decls/stdlib.h>
-#if defined(__GLIBC__) && __cplusplus >= 201703L
+#if defined(__GLIBC__) && __cplusplus >= 201103L
#undef at_quick_exit
#endif
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index cde354c..7633806 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -394,36 +394,48 @@ Interpreter::outOfProcessJITBuilder(JITConfig Config) {
llvm::Expected<std::string>
Interpreter::getOrcRuntimePath(const driver::ToolChain &TC) {
- std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath();
- std::optional<std::string> ResourceDir = TC.getRuntimePath();
+ const std::array<const char *, 3> OrcRTLibNames = {
+ "liborc_rt.a", "liborc_rt_osx.a", "liborc_rt-x86_64.a"};
+
+ auto findInDir = [&](llvm::StringRef Base) -> std::optional<std::string> {
+ for (const char *LibName : OrcRTLibNames) {
+ llvm::SmallString<256> CandidatePath(Base);
+ llvm::sys::path::append(CandidatePath, LibName);
+ if (llvm::sys::fs::exists(CandidatePath))
+ return std::string(CandidatePath.str());
+ }
+ return std::nullopt;
+ };
+
+ std::string SearchedPaths;
- if (!CompilerRTPath) {
+ if (std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath()) {
+ if (auto Found = findInDir(*CompilerRTPath))
+ return *Found;
+ SearchedPaths += *CompilerRTPath;
+ } else {
return llvm::make_error<llvm::StringError>("CompilerRT path not found",
std::error_code());
}
- const std::array<const char *, 3> OrcRTLibNames = {
- "liborc_rt.a", "liborc_rt_osx.a", "liborc_rt-x86_64.a"};
-
- for (const char *LibName : OrcRTLibNames) {
- llvm::SmallString<256> CandidatePath((*CompilerRTPath).c_str());
- llvm::sys::path::append(CandidatePath, LibName);
-
- if (llvm::sys::fs::exists(CandidatePath)) {
- return CandidatePath.str().str();
- }
+ if (std::optional<std::string> ResourceDir = TC.getRuntimePath()) {
+ if (auto Found = findInDir(*ResourceDir))
+ return *Found;
+ if (!SearchedPaths.empty())
+ SearchedPaths += "; ";
+ SearchedPaths += *ResourceDir;
+ } else {
+ return llvm::make_error<llvm::StringError>("ResourceDir path not found",
+ std::error_code());
}
return llvm::make_error<llvm::StringError>(
- llvm::Twine("OrcRuntime library not found in: ") + (*CompilerRTPath),
+ llvm::Twine("OrcRuntime library not found in: ") + SearchedPaths,
std::error_code());
}
llvm::Expected<std::unique_ptr<Interpreter>>
Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) {
- llvm::Error Err = llvm::Error::success();
-
- std::unique_ptr<llvm::orc::LLJITBuilder> JB;
if (Config.IsOutOfProcess) {
const TargetInfo &TI = CI->getTarget();
@@ -453,6 +465,9 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) {
}
}
+ llvm::Error Err = llvm::Error::success();
+ std::unique_ptr<llvm::orc::LLJITBuilder> JB;
+
auto Interp = std::unique_ptr<Interpreter>(new Interpreter(
std::move(CI), Err, std::move(JB), /*Consumer=*/nullptr, Config));
if (auto E = std::move(Err))
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 74f87a8..7a5d28c 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -772,9 +772,11 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// Produce a diagnostic if we're not tentatively parsing; otherwise track
// that our parse has failed.
- auto Invalid = [&](llvm::function_ref<void()> Action) {
+ auto Result = [&](llvm::function_ref<void()> Action,
+ LambdaIntroducerTentativeParse State =
+ LambdaIntroducerTentativeParse::Invalid) {
if (Tentative) {
- *Tentative = LambdaIntroducerTentativeParse::Invalid;
+ *Tentative = State;
return false;
}
Action();
@@ -824,7 +826,7 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
break;
}
- return Invalid([&] {
+ return Result([&] {
Diag(Tok.getLocation(), diag::err_expected_comma_or_rsquare);
});
}
@@ -861,7 +863,7 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
ConsumeToken();
Kind = LCK_StarThis;
} else {
- return Invalid([&] {
+ return Result([&] {
Diag(Tok.getLocation(), diag::err_expected_star_this_capture);
});
}
@@ -875,8 +877,9 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// or the start of a capture (in the "&" case) with the rest of the
// capture missing. Both are an error but a misplaced capture-default
// is more likely if we don't already have a capture default.
- return Invalid(
- [&] { Diag(Tok.getLocation(), diag::err_capture_default_first); });
+ return Result(
+ [&] { Diag(Tok.getLocation(), diag::err_capture_default_first); },
+ LambdaIntroducerTentativeParse::Incomplete);
} else {
TryConsumeToken(tok::ellipsis, EllipsisLocs[0]);
@@ -899,14 +902,13 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
Id = Tok.getIdentifierInfo();
Loc = ConsumeToken();
} else if (Tok.is(tok::kw_this)) {
- return Invalid([&] {
+ return Result([&] {
// FIXME: Suggest a fixit here.
Diag(Tok.getLocation(), diag::err_this_captured_by_reference);
});
} else {
- return Invalid([&] {
- Diag(Tok.getLocation(), diag::err_expected_capture);
- });
+ return Result(
+ [&] { Diag(Tok.getLocation(), diag::err_expected_capture); });
}
TryConsumeToken(tok::ellipsis, EllipsisLocs[2]);
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 31bc941..334438e 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -3178,6 +3178,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_align:
case OMPC_message:
case OMPC_ompx_dyn_cgroup_mem:
+ case OMPC_dyn_groupprivate:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -3216,7 +3217,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
Clause = ParseOpenMPClause(CKind, WrongDirective);
else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||
- CKind == OMPC_num_threads)
+ CKind == OMPC_num_threads || CKind == OMPC_dyn_groupprivate)
Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
else
Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
@@ -4009,6 +4010,83 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
Arg.push_back(OMPC_GRAINSIZE_unknown);
KLoc.emplace_back();
}
+ } else if (Kind == OMPC_dyn_groupprivate) {
+ enum { SimpleModifier, ComplexModifier, NumberOfModifiers };
+ Arg.resize(NumberOfModifiers);
+ KLoc.resize(NumberOfModifiers);
+ Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;
+ Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
+
+ auto ConsumeModifier = [&]() {
+ unsigned Type = NumberOfModifiers;
+ unsigned Modifier;
+ SourceLocation Loc;
+ if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&
+ NextToken().is(tok::l_paren)) {
+ ConsumeToken();
+ BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
+ ParenT.consumeOpen();
+
+ Modifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
+ if (Modifier <= OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown ||
+ Modifier >= OMPC_DYN_GROUPPRIVATE_FALLBACK_last) {
+ Diag(Tok.getLocation(), diag::err_expected)
+ << "'abort', 'null' or 'default_mem' in fallback modifier";
+ SkipUntil(tok::r_paren);
+ return std::make_tuple(Type, Modifier, Loc);
+ }
+ Type = ComplexModifier;
+ Loc = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ ParenT.consumeClose();
+ } else {
+ Modifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
+ if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {
+ Type = SimpleModifier;
+ Loc = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ }
+ }
+ return std::make_tuple(Type, Modifier, Loc);
+ };
+
+ auto SaveModifier = [&](unsigned Type, unsigned Modifier,
+ SourceLocation Loc) {
+ assert(Type < NumberOfModifiers && "Unexpected modifier type");
+ if (!KLoc[Type].isValid()) {
+ Arg[Type] = Modifier;
+ KLoc[Type] = Loc;
+ } else {
+ Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)
+ << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier)
+ << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]);
+ }
+ };
+
+ // Parse 'modifier'
+ auto [Type1, Mod1, Loc1] = ConsumeModifier();
+ if (Type1 < NumberOfModifiers) {
+ SaveModifier(Type1, Mod1, Loc1);
+ if (Tok.is(tok::comma)) {
+ // Parse ',' 'modifier'
+ ConsumeAnyToken();
+ auto [Type2, Mod2, Loc2] = ConsumeModifier();
+ if (Type2 < NumberOfModifiers)
+ SaveModifier(Type2, Mod2, Loc2);
+ }
+ // Parse ':'
+ if (Tok.is(tok::colon))
+ ConsumeAnyToken();
+ else
+ Diag(Tok, diag::warn_pragma_expected_colon)
+ << "dyn_groupprivate modifier";
+ }
} else if (Kind == OMPC_num_tasks) {
// Parse optional <num_tasks modifier> ':'
OpenMPNumTasksClauseModifier Modifier =
@@ -4083,11 +4161,11 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
}
}
- bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
- (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
- Kind == OMPC_if || Kind == OMPC_device ||
- Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
- Kind == OMPC_num_threads;
+ bool NeedAnExpression =
+ (Kind == OMPC_schedule && DelimLoc.isValid()) ||
+ (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if ||
+ Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
+ Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate;
if (NeedAnExpression) {
SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index fb45db1..7e73d89c 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1079,16 +1079,10 @@ bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
StmtResult Parser::handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx) {
bool IsStmtExprResult = false;
if ((StmtCtx & ParsedStmtContext::InStmtExpr) != ParsedStmtContext()) {
- // For GCC compatibility we skip past NullStmts.
- unsigned LookAhead = 0;
- while (GetLookAheadToken(LookAhead).is(tok::semi)) {
- ++LookAhead;
- }
- // Then look to see if the next two tokens close the statement expression;
- // if so, this expression statement is the last statement in a statement
- // expression.
- IsStmtExprResult = GetLookAheadToken(LookAhead).is(tok::r_brace) &&
- GetLookAheadToken(LookAhead + 1).is(tok::r_paren);
+ // Look ahead to see if the next two tokens close the statement expression;
+ // if so, this expression statement is the last statement in a
+ // statment expression.
+ IsStmtExprResult = Tok.is(tok::r_brace) && NextToken().is(tok::r_paren);
}
if (IsStmtExprResult)
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 23bf7f2..46addea 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -321,9 +321,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
static_cast<unsigned>(ComparisonCategoryType::Last) + 1),
StdSourceLocationImplDecl(nullptr), CXXTypeInfoDecl(nullptr),
GlobalNewDeleteDeclared(false), DisableTypoCorrection(false),
- TyposCorrected(0), IsBuildingRecoveryCallExpr(false), NumSFINAEErrors(0),
- AccessCheckingSFINAE(false), CurrentInstantiationScope(nullptr),
- InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
+ TyposCorrected(0), IsBuildingRecoveryCallExpr(false),
+ CurrentInstantiationScope(nullptr), NonInstantiationEntries(0),
ArgPackSubstIndex(std::nullopt), SatisfactionCache(Context) {
assert(pp.TUKind == TUKind);
TUScope = nullptr;
@@ -670,7 +669,9 @@ void Sema::addExternalSource(IntrusiveRefCntPtr<ExternalSemaSource> E) {
void Sema::PrintStats() const {
llvm::errs() << "\n*** Semantic Analysis Stats:\n";
- llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n";
+ if (SFINAETrap *Trap = getSFINAEContext())
+ llvm::errs() << int(Trap->hasErrorOccurred())
+ << " SFINAE diagnostics trapped.\n";
BumpAlloc.PrintStats();
AnalysisWarnings.PrintStats();
@@ -1681,7 +1682,8 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) {
// issue I am not seeing yet), then there should at least be a clarifying
// comment somewhere.
Diagnostic DiagInfo(&Diags, DB);
- if (std::optional<TemplateDeductionInfo *> Info = isSFINAEContext()) {
+ if (SFINAETrap *Trap = getSFINAEContext()) {
+ sema::TemplateDeductionInfo *Info = Trap->getDeductionInfo();
switch (DiagnosticIDs::getDiagnosticSFINAEResponse(DiagInfo.getID())) {
case DiagnosticIDs::SFINAE_Report:
// We'll report the diagnostic below.
@@ -1690,37 +1692,37 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) {
case DiagnosticIDs::SFINAE_SubstitutionFailure:
// Count this failure so that we know that template argument deduction
// has failed.
- ++NumSFINAEErrors;
+ Trap->setErrorOccurred();
// Make a copy of this suppressed diagnostic and store it with the
// template-deduction information.
- if (*Info && !(*Info)->hasSFINAEDiagnostic()) {
- (*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(),
- PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
- }
+ if (Info && !Info->hasSFINAEDiagnostic())
+ Info->addSFINAEDiagnostic(
+ DiagInfo.getLocation(),
+ PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
Diags.setLastDiagnosticIgnored(true);
return;
case DiagnosticIDs::SFINAE_AccessControl: {
// Per C++ Core Issue 1170, access control is part of SFINAE.
- // Additionally, the AccessCheckingSFINAE flag can be used to temporarily
+ // Additionally, the WithAccessChecking flag can be used to temporarily
// make access control a part of SFINAE for the purposes of checking
// type traits.
- if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus11)
+ if (!Trap->withAccessChecking() && !getLangOpts().CPlusPlus11)
break;
SourceLocation Loc = DiagInfo.getLocation();
// Suppress this diagnostic.
- ++NumSFINAEErrors;
+ Trap->setErrorOccurred();
// Make a copy of this suppressed diagnostic and store it with the
// template-deduction information.
- if (*Info && !(*Info)->hasSFINAEDiagnostic()) {
- (*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(),
- PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
- }
+ if (Info && !Info->hasSFINAEDiagnostic())
+ Info->addSFINAEDiagnostic(
+ DiagInfo.getLocation(),
+ PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
Diags.setLastDiagnosticIgnored(true);
@@ -1740,13 +1742,13 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) {
return;
// Make a copy of this suppressed diagnostic and store it with the
// template-deduction information;
- if (*Info) {
- (*Info)->addSuppressedDiagnostic(
+ if (Info) {
+ Info->addSuppressedDiagnostic(
DiagInfo.getLocation(),
PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
if (!Diags.getDiagnosticIDs()->isNote(DiagID))
PrintContextStack([Info](SourceLocation Loc, PartialDiagnostic PD) {
- (*Info)->addSuppressedDiagnostic(Loc, std::move(PD));
+ Info->addSuppressedDiagnostic(Loc, std::move(PD));
});
}
diff --git a/clang/lib/Sema/SemaAMDGPU.cpp b/clang/lib/Sema/SemaAMDGPU.cpp
index 139c4ab..cece220 100644
--- a/clang/lib/Sema/SemaAMDGPU.cpp
+++ b/clang/lib/Sema/SemaAMDGPU.cpp
@@ -558,6 +558,8 @@ AMDGPUMaxNumWorkGroupsAttr *SemaAMDGPU::CreateAMDGPUMaxNumWorkGroupsAttr(
const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr) {
ASTContext &Context = getASTContext();
AMDGPUMaxNumWorkGroupsAttr TmpAttr(Context, CI, XExpr, YExpr, ZExpr);
+ assert(!SemaRef.isSFINAEContext() &&
+ "Can't produce SFINAE diagnostic pointing to temporary attribute");
if (checkAMDGPUMaxNumWorkGroupsArguments(SemaRef, XExpr, YExpr, ZExpr,
TmpAttr))
diff --git a/clang/lib/Sema/SemaBoundsSafety.cpp b/clang/lib/Sema/SemaBoundsSafety.cpp
index 39ab136..de9adf8 100644
--- a/clang/lib/Sema/SemaBoundsSafety.cpp
+++ b/clang/lib/Sema/SemaBoundsSafety.cpp
@@ -132,9 +132,23 @@ bool Sema::CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes,
// `BoundsSafetyCheckUseOfCountAttrPtr`
//
// * When the pointee type is always an incomplete type (e.g.
- // `void`) the attribute is disallowed by this method because we know the
- // type can never be completed so there's no reason to allow it.
- InvalidTypeKind = CountedByInvalidPointeeTypeKind::INCOMPLETE;
+ // `void` in strict C mode) the attribute is disallowed by this method
+ // because we know the type can never be completed so there's no reason
+ // to allow it.
+ //
+ // Exception: void has an implicit size of 1 byte for pointer arithmetic
+ // (following GNU convention). Therefore, counted_by on void* is allowed
+ // and behaves equivalently to sized_by (treating the count as bytes).
+ bool IsVoidPtr = PointeeTy->isVoidType();
+ if (IsVoidPtr) {
+ // Emit a warning that this is a GNU extension.
+ Diag(FD->getBeginLoc(), diag::ext_gnu_counted_by_void_ptr) << Kind;
+ Diag(FD->getBeginLoc(), diag::note_gnu_counted_by_void_ptr_use_sized_by)
+ << Kind;
+ assert(InvalidTypeKind == CountedByInvalidPointeeTypeKind::VALID);
+ } else {
+ InvalidTypeKind = CountedByInvalidPointeeTypeKind::INCOMPLETE;
+ }
} else if (PointeeTy->isSizelessType()) {
InvalidTypeKind = CountedByInvalidPointeeTypeKind::SIZELESS;
} else if (PointeeTy->isFunctionType()) {
@@ -272,6 +286,9 @@ GetCountedByAttrOnIncompletePointee(QualType Ty, NamedDecl **ND) {
if (!PointeeTy->isIncompleteType(ND))
return {};
+ if (PointeeTy->isVoidType())
+ return {};
+
return {CATy, PointeeTy};
}
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index fb4d0b45..883e341 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -526,12 +526,12 @@ ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
S, AtomicExpr->getBeginLoc(),
Sema::InstantiatingTemplate::ConstraintSubstitution{},
// FIXME: improve const-correctness of InstantiatingTemplate
- const_cast<NamedDecl *>(Template), Info, AtomicExpr->getSourceRange());
+ const_cast<NamedDecl *>(Template), AtomicExpr->getSourceRange());
if (Inst.isInvalid())
return ExprError();
// We do not want error diagnostics escaping here.
- Sema::SFINAETrap Trap(S);
+ Sema::SFINAETrap Trap(S, Info);
SubstitutedExpression =
S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
@@ -599,16 +599,15 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
return MultiLevelTemplateArgumentList();
TemplateDeductionInfo Info(Constraint.getBeginLoc());
+ Sema::SFINAETrap Trap(S, Info);
Sema::InstantiatingTemplate Inst(
S, Constraint.getBeginLoc(),
Sema::InstantiatingTemplate::ConstraintSubstitution{},
// FIXME: improve const-correctness of InstantiatingTemplate
- const_cast<NamedDecl *>(Template), Info, Constraint.getSourceRange());
+ const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
if (Inst.isInvalid())
return std::nullopt;
- Sema::SFINAETrap Trap(S);
-
TemplateArgumentListInfo SubstArgs;
Sema::ArgPackSubstIndexRAII SubstIndex(
S, Constraint.getPackSubstitutionIndex()
@@ -778,9 +777,6 @@ ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
const FoldExpandedConstraint &FE,
const MultiLevelTemplateArgumentList &MLTAL) {
- // We should ignore errors in the presence of packs of different size.
- Sema::SFINAETrap Trap(S);
-
Expr *Pattern = const_cast<Expr *>(FE.getPattern());
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
@@ -792,18 +788,12 @@ ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
if (S.CheckParameterPacksForExpansion(
Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
/*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion,
- NumExpansions) ||
+ NumExpansions, /*Diagnose=*/false) ||
!Expand || RetainExpansion)
return std::nullopt;
- if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions) {
- S.Diag(Pattern->getExprLoc(),
- clang::diag::err_fold_expression_limit_exceeded)
- << *NumExpansions << S.getLangOpts().BracketDepth
- << Pattern->getSourceRange();
- S.Diag(Pattern->getExprLoc(), diag::note_bracket_depth);
+ if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions)
return std::nullopt;
- }
return NumExpansions;
}
@@ -921,7 +911,6 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
return ExprError();
}
- Sema::SFINAETrap Trap(S);
Sema::ArgPackSubstIndexRAII SubstIndex(
S, Constraint.getPackSubstitutionIndex()
? Constraint.getPackSubstitutionIndex()
@@ -930,9 +919,10 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
const ASTTemplateArgumentListInfo *Ori =
ConceptId->getTemplateArgsAsWritten();
TemplateDeductionInfo Info(TemplateNameLoc);
- Sema::InstantiatingTemplate _(
+ Sema::SFINAETrap Trap(S, Info);
+ Sema::InstantiatingTemplate _2(
S, TemplateNameLoc, Sema::InstantiatingTemplate::ConstraintSubstitution{},
- const_cast<NamedDecl *>(Template), Info, Constraint.getSourceRange());
+ const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
TemplateArgumentListInfo OutArgs(Ori->LAngleLoc, Ori->RAngleLoc);
if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs, OutArgs) ||
@@ -1142,13 +1132,21 @@ static bool CheckConstraintSatisfaction(
if (TemplateArgsLists.getNumLevels() != 0)
Args = TemplateArgsLists.getInnermost();
- std::optional<Sema::InstantiatingTemplate> SynthesisContext;
- if (!TopLevelConceptId) {
- SynthesisContext.emplace(S, TemplateIDRange.getBegin(),
- Sema::InstantiatingTemplate::ConstraintsCheck{},
- const_cast<NamedDecl *>(Template), Args,
+ struct SynthesisContextPair {
+ Sema::InstantiatingTemplate Inst;
+ Sema::NonSFINAEContext NSC;
+ SynthesisContextPair(Sema &S, NamedDecl *Template,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange)
+ : Inst(S, InstantiationRange.getBegin(),
+ Sema::InstantiatingTemplate::ConstraintsCheck{}, Template,
+ TemplateArgs, InstantiationRange),
+ NSC(S) {}
+ };
+ std::optional<SynthesisContextPair> SynthesisContext;
+ if (!TopLevelConceptId)
+ SynthesisContext.emplace(S, const_cast<NamedDecl *>(Template), Args,
TemplateIDRange);
- }
const NormalizedConstraint *C =
S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);
@@ -1478,8 +1476,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
if (MLTAL.getNumSubstitutedLevels() == 0)
return ConstrExpr;
- Sema::SFINAETrap SFINAE(S);
-
+ Sema::NonSFINAEContext _(S);
Sema::InstantiatingTemplate Inst(
S, DeclInfo.getLocation(),
Sema::InstantiatingTemplate::ConstraintNormalization{},
@@ -1554,7 +1551,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
Sema::ReuseLambdaContextDecl);
ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(
const_cast<clang::Expr *>(ConstrExpr), MLTAL);
- if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
+ if (!SubstConstr.isUsable())
return nullptr;
return SubstConstr.get();
}
@@ -2104,6 +2101,7 @@ bool SubstituteParameterMappings::substitute(
InstLocBegin = SR.getBegin();
InstLocEnd = SR.getEnd();
}
+ Sema::NonSFINAEContext _(SemaRef);
Sema::InstantiatingTemplate Inst(
SemaRef, InstLocBegin,
Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
@@ -2171,6 +2169,7 @@ bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) {
InstLocBegin = SR.getBegin();
InstLocEnd = SR.getEnd();
}
+ Sema::NonSFINAEContext _(SemaRef);
// This is useful for name lookup across modules; see Sema::getLookupModules.
Sema::InstantiatingTemplate Inst(
SemaRef, InstLocBegin,
@@ -2311,6 +2310,7 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
} else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
NormalizedConstraint *SubNF;
{
+ Sema::NonSFINAEContext _(S);
Sema::InstantiatingTemplate Inst(
S, CSE->getExprLoc(),
Sema::InstantiatingTemplate::ConstraintNormalization{},
@@ -2546,8 +2546,6 @@ bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
};
{
- // The subsumption checks might cause diagnostics
- SFINAETrap Trap(*this);
auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
if (!Normalized1)
return false;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index fc3aabf..086dd8b 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8492,12 +8492,11 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
DeclContext *NewDC = D->getDeclContext();
if (FieldDecl *FD = dyn_cast<FieldDecl>(ShadowedDecl)) {
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewDC)) {
- // Fields are not shadowed by variables in C++ static methods.
- if (MD->isStatic())
- return;
-
- if (!MD->getParent()->isLambda() && MD->isExplicitObjectMemberFunction())
+ if (const auto *MD =
+ dyn_cast<CXXMethodDecl>(getFunctionLevelDeclContext())) {
+ // Fields aren't shadowed in C++ static members or in member functions
+ // with an explicit object parameter.
+ if (MD->isStatic() || MD->isExplicitObjectMemberFunction())
return;
}
// Fields shadowed by constructor parameters are a special case. Usually
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a50c276..2159a0d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -12653,10 +12653,10 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
// This is a gcc extension compatibility comparison.
// In a SFINAE context, we treat this as a hard error to maintain
// conformance with the C++ standard.
- diagnoseFunctionPointerToVoidComparison(
- *this, Loc, LHS, RHS, /*isError*/ (bool)isSFINAEContext());
+ bool IsError = isSFINAEContext();
+ diagnoseFunctionPointerToVoidComparison(*this, Loc, LHS, RHS, IsError);
- if (isSFINAEContext())
+ if (IsError)
return QualType();
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
@@ -14598,11 +14598,11 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
unsigned AddressOfError = AO_No_Error;
if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
- bool sfinae = (bool)isSFINAEContext();
- Diag(OpLoc, isSFINAEContext() ? diag::err_typecheck_addrof_temporary
- : diag::ext_typecheck_addrof_temporary)
- << op->getType() << op->getSourceRange();
- if (sfinae)
+ bool IsError = isSFINAEContext();
+ Diag(OpLoc, IsError ? diag::err_typecheck_addrof_temporary
+ : diag::ext_typecheck_addrof_temporary)
+ << op->getType() << op->getSourceRange();
+ if (IsError)
return QualType();
// Materialize the temporary as an lvalue so that we can take its address.
OrigOp = op =
@@ -16185,9 +16185,7 @@ ExprResult Sema::BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
QualType Ty = Context.VoidTy;
bool StmtExprMayBindToTemp = false;
if (!Compound->body_empty()) {
- // For GCC compatibility we get the last Stmt excluding trailing NullStmts.
- if (const auto *LastStmt =
- dyn_cast<ValueStmt>(Compound->getStmtExprResult())) {
+ if (const auto *LastStmt = dyn_cast<ValueStmt>(Compound->body_back())) {
if (const Expr *Value = LastStmt->getExprStmt()) {
StmtExprMayBindToTemp = true;
Ty = Value->getType();
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 256f952..465dab2 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -16532,6 +16532,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
case OMPC_holds:
Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_dyn_groupprivate:
case OMPC_grainsize:
case OMPC_num_tasks:
case OMPC_num_threads:
@@ -16658,6 +16659,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPC_num_teams:
case OMPC_thread_limit:
case OMPC_ompx_dyn_cgroup_mem:
+ case OMPC_dyn_groupprivate:
+ // TODO: This may need to consider teams too.
if (Leafs[0] == OMPD_target)
return OMPD_target;
break;
@@ -17705,7 +17708,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
SourceLocation EndLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
- case OMPC_schedule:
+ case OMPC_schedule: {
enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
assert(Argument.size() == NumberOfElements &&
ArgumentLoc.size() == NumberOfElements);
@@ -17716,6 +17719,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
break;
+ }
case OMPC_if:
assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
@@ -17771,6 +17775,20 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
break;
+ case OMPC_dyn_groupprivate: {
+ enum { Modifier1, Modifier2, NumberOfElements };
+ assert(Argument.size() == NumberOfElements &&
+ ArgumentLoc.size() == NumberOfElements &&
+ "Modifiers for dyn_groupprivate clause and their locations are "
+ "expected.");
+ Res = ActOnOpenMPDynGroupprivateClause(
+ static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
+ static_cast<OpenMPDynGroupprivateClauseFallbackModifier>(
+ Argument[Modifier2]),
+ Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
+ ArgumentLoc[Modifier2], EndLoc);
+ break;
+ }
case OMPC_num_threads:
assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
"Modifier for num_threads clause and its location are expected.");
@@ -18127,6 +18145,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_affinity:
case OMPC_when:
case OMPC_ompx_dyn_cgroup_mem:
+ case OMPC_dyn_groupprivate:
default:
llvm_unreachable("Clause is not allowed.");
}
@@ -25246,6 +25265,49 @@ OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
}
+OMPClause *SemaOpenMP::ActOnOpenMPDynGroupprivateClause(
+ OpenMPDynGroupprivateClauseModifier M1,
+ OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
+ SourceLocation M2Loc, SourceLocation EndLoc) {
+
+ if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
+ (M2Loc.isValid() && M2 == OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown)) {
+ std::string Values = getListOfPossibleValues(
+ OMPC_dyn_groupprivate, /*First=*/0, OMPC_DYN_GROUPPRIVATE_unknown);
+ Diag((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
+ : M2Loc,
+ diag::err_omp_unexpected_clause_value)
+ << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
+ return nullptr;
+ }
+
+ Expr *ValExpr = Size;
+ Stmt *HelperValStmt = nullptr;
+
+ // OpenMP [2.5, Restrictions]
+ // The dyn_groupprivate expression must evaluate to a positive integer
+ // value.
+ if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_dyn_groupprivate,
+ /*StrictlyPositive=*/false))
+ return nullptr;
+
+ OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
+ OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
+ DKind, OMPC_dyn_groupprivate, getLangOpts().OpenMP);
+ if (CaptureRegion != OMPD_unknown &&
+ !SemaRef.CurContext->isDependentContext()) {
+ ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
+ ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
+ HelperValStmt = buildPreInits(getASTContext(), Captures);
+ }
+
+ return new (getASTContext()) OMPDynGroupprivateClause(
+ StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
+ M1Loc, M2, M2Loc);
+}
+
OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 983a784..4a9e1bc 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3846,13 +3846,14 @@ QualType Sema::CheckTemplateIdType(ElaboratedTypeKeyword Keyword,
// within enable_if in a SFINAE context, dig out the specific
// enable_if condition that failed and present that instead.
if (isEnableIfAliasTemplate(AliasTemplate)) {
- if (auto DeductionInfo = isSFINAEContext()) {
- if (*DeductionInfo &&
- (*DeductionInfo)->hasSFINAEDiagnostic() &&
- (*DeductionInfo)->peekSFINAEDiagnostic().second.getDiagID() ==
- diag::err_typename_nested_not_found_enable_if &&
- TemplateArgs[0].getArgument().getKind()
- == TemplateArgument::Expression) {
+ if (SFINAETrap *Trap = getSFINAEContext();
+ TemplateDeductionInfo *DeductionInfo =
+ Trap ? Trap->getDeductionInfo() : nullptr) {
+ if (DeductionInfo->hasSFINAEDiagnostic() &&
+ DeductionInfo->peekSFINAEDiagnostic().second.getDiagID() ==
+ diag::err_typename_nested_not_found_enable_if &&
+ TemplateArgs[0].getArgument().getKind() ==
+ TemplateArgument::Expression) {
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
@@ -3861,15 +3862,14 @@ QualType Sema::CheckTemplateIdType(ElaboratedTypeKeyword Keyword,
// Remove the old SFINAE diagnostic.
PartialDiagnosticAt OldDiag =
{SourceLocation(), PartialDiagnostic::NullDiagnostic()};
- (*DeductionInfo)->takeSFINAEDiagnostic(OldDiag);
+ DeductionInfo->takeSFINAEDiagnostic(OldDiag);
// Add a new SFINAE diagnostic specifying which condition
// failed.
- (*DeductionInfo)->addSFINAEDiagnostic(
- OldDiag.first,
- PDiag(diag::err_typename_nested_not_found_requirement)
- << FailedDescription
- << FailedCond->getSourceRange());
+ DeductionInfo->addSFINAEDiagnostic(
+ OldDiag.first,
+ PDiag(diag::err_typename_nested_not_found_requirement)
+ << FailedDescription << FailedCond->getSourceRange());
}
}
}
@@ -3955,6 +3955,7 @@ QualType Sema::CheckTemplateIdType(ElaboratedTypeKeyword Keyword,
if (Decl->getSpecializationKind() == TSK_Undeclared &&
ClassTemplate->getTemplatedDecl()->hasAttrs()) {
+ NonSFINAEContext _(*this);
InstantiatingTemplate Inst(*this, TemplateLoc, Decl);
if (!Inst.isInvalid()) {
MultiLevelTemplateArgumentList TemplateArgLists(Template,
@@ -5565,12 +5566,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
auto checkExpr = [&](Expr *E) -> Expr * {
TemplateArgument SugaredResult, CanonicalResult;
- unsigned CurSFINAEErrors = NumSFINAEErrors;
ExprResult Res = CheckTemplateArgument(
NTTP, NTTPType, E, SugaredResult, CanonicalResult,
/*StrictCheck=*/CTAI.MatchingTTP || CTAI.PartialOrdering, CTAK);
// If the current template argument causes an error, give up now.
- if (Res.isInvalid() || CurSFINAEErrors < NumSFINAEErrors)
+ if (Res.isInvalid())
return nullptr;
CTAI.SugaredConverted.push_back(SugaredResult);
CTAI.CanonicalConverted.push_back(CanonicalResult);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 6964242..a287319 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3239,10 +3239,6 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction(
ArrayRef<TemplateArgumentLoc> Ps, ArrayRef<TemplateArgument> As,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info, bool CopyDeducedArgs) {
- // Unevaluated SFINAE context.
- EnterExpressionEvaluationContext Unevaluated(
- S, Sema::ExpressionEvaluationContext::Unevaluated);
-
Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(Entity));
// C++ [temp.deduct.type]p2:
@@ -3380,10 +3376,6 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction(
Sema &S, TemplateDecl *TD,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info) {
- // Unevaluated SFINAE context.
- EnterExpressionEvaluationContext Unevaluated(
- S, Sema::ExpressionEvaluationContext::Unevaluated);
-
Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(TD));
// C++ [temp.deduct.type]p2:
@@ -3423,7 +3415,7 @@ DeduceTemplateArguments(Sema &S, T *Partial,
// Unevaluated SFINAE context.
EnterExpressionEvaluationContext Unevaluated(
S, Sema::ExpressionEvaluationContext::Unevaluated);
- Sema::SFINAETrap Trap(S);
+ Sema::SFINAETrap Trap(S, Info);
// This deduction has no relation to any outer instantiation we might be
// performing.
@@ -3441,8 +3433,7 @@ DeduceTemplateArguments(Sema &S, T *Partial,
return Result;
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
- Sema::InstantiatingTemplate Inst(S, Info.getLocation(), Partial, DeducedArgs,
- Info);
+ Sema::InstantiatingTemplate Inst(S, Info.getLocation(), Partial, DeducedArgs);
if (Inst.isInvalid())
return TemplateDeductionResult::InstantiationDepth;
@@ -3497,7 +3488,7 @@ Sema::DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType,
// Unevaluated SFINAE context.
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
- SFINAETrap Trap(*this);
+ SFINAETrap Trap(*this, Info);
// This deduction has no relation to any outer instantiation we might be
// performing.
@@ -3514,7 +3505,7 @@ Sema::DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType,
}
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
- InstantiatingTemplate Inst(*this, Info.getLocation(), TD, DeducedArgs, Info);
+ InstantiatingTemplate Inst(*this, Info.getLocation(), TD, DeducedArgs);
if (Inst.isInvalid())
return TemplateDeductionResult::InstantiationDepth;
@@ -3558,6 +3549,9 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType,
TemplateDeductionInfo &Info) {
+ assert(isSFINAEContext());
+ assert(isUnevaluatedContext());
+
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
@@ -3573,11 +3567,6 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
return TemplateDeductionResult::Success;
}
- // Unevaluated SFINAE context.
- EnterExpressionEvaluationContext Unevaluated(
- *this, Sema::ExpressionEvaluationContext::Unevaluated);
- SFINAETrap Trap(*this);
-
// C++ [temp.arg.explicit]p3:
// Template arguments that are present shall be specified in the
// declaration order of their corresponding template-parameters. The
@@ -3590,7 +3579,7 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
SmallVector<TemplateArgument, 4> DeducedArgs;
InstantiatingTemplate Inst(
*this, Info.getLocation(), FunctionTemplate, DeducedArgs,
- CodeSynthesisContext::ExplicitTemplateArgumentSubstitution, Info);
+ CodeSynthesisContext::ExplicitTemplateArgumentSubstitution);
if (Inst.isInvalid())
return TemplateDeductionResult::InstantiationDepth;
@@ -3598,8 +3587,7 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
if (CheckTemplateArgumentList(FunctionTemplate, SourceLocation(),
ExplicitTemplateArgs, /*DefaultArgs=*/{},
/*PartialTemplateArgs=*/true, CTAI,
- /*UpdateArgsWithConversions=*/false) ||
- Trap.hasErrorOccurred()) {
+ /*UpdateArgsWithConversions=*/false)) {
unsigned Index = CTAI.SugaredConverted.size();
if (Index >= TemplateParams->size())
return TemplateDeductionResult::SubstitutionFailure;
@@ -3688,7 +3676,7 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
ResultType =
SubstType(Proto->getReturnType(), MLTAL,
Function->getTypeSpecStartLoc(), Function->getDeclName());
- if (ResultType.isNull() || Trap.hasErrorOccurred())
+ if (ResultType.isNull())
return TemplateDeductionResult::SubstitutionFailure;
// CUDA: Kernel function must have 'void' return type.
if (getLangOpts().CUDA)
@@ -3714,7 +3702,7 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
Function->getLocation(),
Function->getDeclName(),
EPI);
- if (FunctionType->isNull() || Trap.hasErrorOccurred())
+ if (FunctionType->isNull())
return TemplateDeductionResult::SubstitutionFailure;
}
@@ -3912,12 +3900,15 @@ static TemplateDeductionResult instantiateExplicitSpecifierDeferred(
if (!ExplicitExpr->isValueDependent())
return TemplateDeductionResult::Success;
+ // By this point, FinishTemplateArgumentDeduction will have been reverted back
+ // to a regular non-SFINAE template instantiation context, so setup a new
+ // SFINAE context.
Sema::InstantiatingTemplate Inst(
S, Info.getLocation(), FunctionTemplate, DeducedArgs,
- Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
+ Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution);
if (Inst.isInvalid())
return TemplateDeductionResult::InstantiationDepth;
- Sema::SFINAETrap Trap(S);
+ Sema::SFINAETrap Trap(S, Info);
const ExplicitSpecifier InstantiatedES =
S.instantiateExplicitSpecifier(SubstArgs, ES);
if (InstantiatedES.isInvalid() || Trap.hasErrorOccurred()) {
@@ -3937,17 +3928,12 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
bool PartialOverloading, bool PartialOrdering,
bool ForOverloadSetAddressResolution,
llvm::function_ref<bool(bool)> CheckNonDependent) {
- // Unevaluated SFINAE context.
- EnterExpressionEvaluationContext Unevaluated(
- *this, Sema::ExpressionEvaluationContext::Unevaluated);
- SFINAETrap Trap(*this);
-
// Enter a new template instantiation context while we instantiate the
// actual function declaration.
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
InstantiatingTemplate Inst(
*this, Info.getLocation(), FunctionTemplate, DeducedArgs,
- CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
+ CodeSynthesisContext::DeducedTemplateArgumentSubstitution);
if (Inst.isInvalid())
return TemplateDeductionResult::InstantiationDepth;
@@ -4030,18 +4016,9 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
// If the template argument list is owned by the function template
// specialization, release it.
if (Specialization->getTemplateSpecializationArgs() ==
- CanonicalDeducedArgumentList &&
- !Trap.hasErrorOccurred())
+ CanonicalDeducedArgumentList)
Info.takeCanonical();
- // There may have been an error that did not prevent us from constructing a
- // declaration. Mark the declaration invalid and return with a substitution
- // failure.
- if (Trap.hasErrorOccurred()) {
- Specialization->setInvalidDecl(true);
- return TemplateDeductionResult::SubstitutionFailure;
- }
-
// C++2a [temp.deduct]p5
// [...] When all template arguments have been deduced [...] all uses of
// template parameters [...] are replaced with the corresponding deduced
@@ -4553,6 +4530,10 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
return TemplateDeductionResult::TooManyArguments;
}
+ EnterExpressionEvaluationContext Unevaluated(
+ *this, Sema::ExpressionEvaluationContext::Unevaluated);
+ Sema::SFINAETrap Trap(*this, Info);
+
// The types of the parameters from which we will perform template argument
// deduction.
LocalInstantiationScope InstScope(*this);
@@ -4570,6 +4551,8 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
});
if (Result != TemplateDeductionResult::Success)
return Result;
+ if (Trap.hasErrorOccurred())
+ return TemplateDeductionResult::SubstitutionFailure;
NumExplicitlySpecified = Deduced.size();
} else {
@@ -4743,6 +4726,11 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
OnlyInitializeNonUserDefinedConversions);
});
});
+ if (Trap.hasErrorOccurred()) {
+ if (Specialization)
+ Specialization->setInvalidDecl(true);
+ return TemplateDeductionResult::SubstitutionFailure;
+ }
return Result;
}
@@ -4795,6 +4783,14 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
= FunctionTemplate->getTemplateParameters();
QualType FunctionType = Function->getType();
+ bool PotentiallyEvaluated =
+ currentEvaluationContext().isPotentiallyEvaluated();
+
+ // Unevaluated SFINAE context.
+ EnterExpressionEvaluationContext Unevaluated(
+ *this, Sema::ExpressionEvaluationContext::Unevaluated);
+ SFINAETrap Trap(*this, Info);
+
// Substitute any explicit template arguments.
LocalInstantiationScope InstScope(*this);
SmallVector<DeducedTemplateArgument, 4> Deduced;
@@ -4809,6 +4805,8 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
});
if (Result != TemplateDeductionResult::Success)
return Result;
+ if (Trap.hasErrorOccurred())
+ return TemplateDeductionResult::SubstitutionFailure;
NumExplicitlySpecified = Deduced.size();
}
@@ -4820,11 +4818,6 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType,
/*AdjustExceptionSpec*/false);
- // Unevaluated SFINAE context.
- std::optional<EnterExpressionEvaluationContext> Unevaluated(
- std::in_place, *this, Sema::ExpressionEvaluationContext::Unevaluated);
- SFINAETrap Trap(*this);
-
Deduced.resize(TemplateParams->size());
// If the function has a deduced return type, substitute it for a dependent
@@ -4865,14 +4858,12 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
DeduceReturnType(Specialization, Info.getLocation(), false))
return TemplateDeductionResult::MiscellaneousDeductionFailure;
- Unevaluated = std::nullopt;
// [C++26][expr.const]/p17
// An expression or conversion is immediate-escalating if it is not initially
// in an immediate function context and it is [...]
// a potentially-evaluated id-expression that denotes an immediate function.
if (IsAddressOfFunction && getLangOpts().CPlusPlus20 &&
- Specialization->isImmediateEscalating() &&
- currentEvaluationContext().isPotentiallyEvaluated() &&
+ Specialization->isImmediateEscalating() && PotentiallyEvaluated &&
CheckIfFunctionSpecializationIsImmediate(Specialization,
Info.getLocation()))
return TemplateDeductionResult::MiscellaneousDeductionFailure;
@@ -4975,7 +4966,7 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
// Unevaluated SFINAE context.
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
- SFINAETrap Trap(*this);
+ SFINAETrap Trap(*this, Info);
// C++ [temp.deduct.conv]p1:
// Template argument deduction is done by comparing the return
@@ -5614,10 +5605,6 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction(
Sema &S, FunctionTemplateDecl *FTD,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info, T &&CheckDeductionConsistency) {
- EnterExpressionEvaluationContext Unevaluated(
- S, Sema::ExpressionEvaluationContext::Unevaluated);
- Sema::SFINAETrap Trap(S);
-
Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(FTD));
// C++26 [temp.deduct.type]p2:
@@ -5645,13 +5632,7 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction(
// and verify that the instantiated argument is both valid
// and equivalent to the parameter.
LocalInstantiationScope InstScope(S);
-
- if (auto TDR = CheckDeductionConsistency(S, FTD, CTAI.SugaredConverted);
- TDR != TemplateDeductionResult::Success)
- return TDR;
-
- return Trap.hasErrorOccurred() ? TemplateDeductionResult::SubstitutionFailure
- : TemplateDeductionResult::Success;
+ return CheckDeductionConsistency(S, FTD, CTAI.SugaredConverted);
}
/// Determine whether the function template \p FT1 is at least as
@@ -5717,9 +5698,12 @@ static bool isAtLeastAsSpecializedAs(
}
SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
+ EnterExpressionEvaluationContext Unevaluated(
+ S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Sema::SFINAETrap Trap(S, Info);
Sema::InstantiatingTemplate Inst(
S, Info.getLocation(), FT2, DeducedArgs,
- Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
+ Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution);
if (Inst.isInvalid())
return false;
@@ -5765,7 +5749,7 @@ static bool isAtLeastAsSpecializedAs(
});
}) == TemplateDeductionResult::Success;
});
- if (!AtLeastAsSpecialized)
+ if (!AtLeastAsSpecialized || Trap.hasErrorOccurred())
return false;
// C++0x [temp.deduct.partial]p11:
@@ -6241,10 +6225,11 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
/*HasDeducedAnyParam=*/nullptr) != TemplateDeductionResult::Success)
return false;
- SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
- Deduced.end());
- Sema::InstantiatingTemplate Inst(S, Info.getLocation(), P2, DeducedArgs,
- Info);
+ SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
+ EnterExpressionEvaluationContext Unevaluated(
+ S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Sema::SFINAETrap Trap(S, Info);
+ Sema::InstantiatingTemplate Inst(S, Info.getLocation(), P2, DeducedArgs);
if (Inst.isInvalid())
return false;
@@ -6252,8 +6237,6 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
Ps = cast<TemplateSpecializationType>(T2)->template_arguments(),
As = cast<TemplateSpecializationType>(T1)->template_arguments();
- Sema::SFINAETrap Trap(S);
-
TemplateDeductionResult Result;
S.runWithSufficientStackSpace(Info.getLocation(), [&] {
Result = ::FinishTemplateArgumentDeduction(
@@ -6261,14 +6244,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
/*IsPartialOrdering=*/true, Ps, As, Deduced, Info,
/*CopyDeducedArgs=*/false);
});
-
- if (Result != TemplateDeductionResult::Success)
- return false;
-
- if (Trap.hasErrorOccurred())
- return false;
-
- return true;
+ return Result == TemplateDeductionResult::Success && !Trap.hasErrorOccurred();
}
namespace {
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 40811d4..bfb1066 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -1025,6 +1025,7 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
TypeAliasTemplateDecl *AliasTemplate,
FunctionTemplateDecl *F, SourceLocation Loc) {
LocalInstantiationScope Scope(SemaRef);
+ Sema::NonSFINAEContext _1(SemaRef);
Sema::InstantiatingTemplate BuildingDeductionGuides(
SemaRef, AliasTemplate->getLocation(), F,
Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 5fceacd..35205f4 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -606,8 +606,7 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind,
SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
- Decl *Entity, NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo *DeductionInfo)
+ Decl *Entity, NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs)
: SemaRef(SemaRef) {
// Don't allow further instantiation if a fatal error and an uncompilable
// error have occurred. Any diagnostics we might have raised will not be
@@ -625,7 +624,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Inst.Template = Template;
Inst.TemplateArgs = TemplateArgs.data();
Inst.NumTemplateArgs = TemplateArgs.size();
- Inst.DeductionInfo = DeductionInfo;
Inst.InstantiationRange = InstantiationRange;
Inst.InConstraintSubstitution =
Inst.Kind == CodeSynthesisContext::ConstraintSubstitution;
@@ -671,48 +669,40 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
FunctionTemplateDecl *FunctionTemplate,
ArrayRef<TemplateArgument> TemplateArgs,
- CodeSynthesisContext::SynthesisKind Kind,
- sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+ CodeSynthesisContext::SynthesisKind Kind, SourceRange InstantiationRange)
: InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation,
InstantiationRange, FunctionTemplate, nullptr,
- TemplateArgs, &DeductionInfo) {
+ TemplateArgs) {
assert(Kind == CodeSynthesisContext::ExplicitTemplateArgumentSubstitution ||
Kind == CodeSynthesisContext::DeducedTemplateArgumentSubstitution ||
Kind == CodeSynthesisContext::BuildingDeductionGuides);
}
Sema::InstantiatingTemplate::InstantiatingTemplate(
- Sema &SemaRef, SourceLocation PointOfInstantiation,
- TemplateDecl *Template,
- ArrayRef<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+ Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template,
+ ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
: InstantiatingTemplate(
- SemaRef,
- CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+ SemaRef, CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
PointOfInstantiation, InstantiationRange, Template, nullptr,
- TemplateArgs, &DeductionInfo) {}
+ TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
ClassTemplatePartialSpecializationDecl *PartialSpec,
- ArrayRef<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+ ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
: InstantiatingTemplate(
- SemaRef,
- CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+ SemaRef, CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
PointOfInstantiation, InstantiationRange, PartialSpec, nullptr,
- TemplateArgs, &DeductionInfo) {}
+ TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
VarTemplatePartialSpecializationDecl *PartialSpec,
- ArrayRef<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+ ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
: InstantiatingTemplate(
- SemaRef,
- CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+ SemaRef, CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
PointOfInstantiation, InstantiationRange, PartialSpec, nullptr,
- TemplateArgs, &DeductionInfo) {}
+ TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation, ParmVarDecl *Param,
@@ -763,12 +753,11 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
- concepts::Requirement *Req, sema::TemplateDeductionInfo &DeductionInfo,
- SourceRange InstantiationRange)
+ concepts::Requirement *Req, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::RequirementInstantiation,
PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr,
- /*Template=*/nullptr, /*TemplateArgs=*/{}, &DeductionInfo) {}
+ /*Template=*/nullptr, /*TemplateArgs=*/{}) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -781,11 +770,11 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation, const RequiresExpr *RE,
- sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+ SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::RequirementParameterInstantiation,
PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr,
- /*Template=*/nullptr, /*TemplateArgs=*/{}, &DeductionInfo) {}
+ /*Template=*/nullptr, /*TemplateArgs=*/{}) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -797,13 +786,11 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
- Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintSubstitution, NamedDecl *Template,
- sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+ Sema &SemaRef, SourceLocation PointOfInstantiation, ConstraintSubstitution,
+ NamedDecl *Template, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::ConstraintSubstitution,
- PointOfInstantiation, InstantiationRange, Template, nullptr,
- {}, &DeductionInfo) {}
+ PointOfInstantiation, InstantiationRange, Template, nullptr, {}) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -835,9 +822,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
ArgLoc, InstantiationRange, PArg) {}
bool Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
- Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
- InNonInstantiationSFINAEContext = false;
-
if (!Ctx.isInstantiationRecord()) {
++NonInstantiationEntries;
} else {
@@ -871,8 +855,6 @@ void Sema::popCodeSynthesisContext() {
--NonInstantiationEntries;
}
- InNonInstantiationSFINAEContext = Active.SavedInNonInstantiationSFINAEContext;
-
// Name lookup no longer looks in this template's defining module.
assert(CodeSynthesisContexts.size() >=
CodeSynthesisContextLookupModules.size() &&
@@ -1282,93 +1264,6 @@ void Sema::PrintInstantiationStack(InstantiationContextDiagFuncRef DiagFunc) {
}
}
-std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
- if (InNonInstantiationSFINAEContext)
- return std::optional<TemplateDeductionInfo *>(nullptr);
-
- for (SmallVectorImpl<CodeSynthesisContext>::const_reverse_iterator
- Active = CodeSynthesisContexts.rbegin(),
- ActiveEnd = CodeSynthesisContexts.rend();
- Active != ActiveEnd;
- ++Active)
- {
- switch (Active->Kind) {
- case CodeSynthesisContext::TypeAliasTemplateInstantiation:
- // An instantiation of an alias template may or may not be a SFINAE
- // context, depending on what else is on the stack.
- if (isa<TypeAliasTemplateDecl>(Active->Entity))
- break;
- [[fallthrough]];
- case CodeSynthesisContext::TemplateInstantiation:
- case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
- case CodeSynthesisContext::ExceptionSpecInstantiation:
- case CodeSynthesisContext::ConstraintsCheck:
- case CodeSynthesisContext::ParameterMappingSubstitution:
- case CodeSynthesisContext::ConstraintNormalization:
- case CodeSynthesisContext::NestedRequirementConstraintsCheck:
- // This is a template instantiation, so there is no SFINAE.
- return std::nullopt;
- case CodeSynthesisContext::LambdaExpressionSubstitution:
- // [temp.deduct]p9
- // A lambda-expression appearing in a function type or a template
- // parameter is not considered part of the immediate context for the
- // purposes of template argument deduction.
- // CWG2672: A lambda-expression body is never in the immediate context.
- return std::nullopt;
-
- case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
- case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
- case CodeSynthesisContext::DefaultTemplateArgumentChecking:
- case CodeSynthesisContext::RewritingOperatorAsSpaceship:
- case CodeSynthesisContext::PartialOrderingTTP:
- // A default template argument instantiation and substitution into
- // template parameters with arguments for prior parameters may or may
- // not be a SFINAE context; look further up the stack.
- break;
-
- case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
- case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
- // We're either substituting explicitly-specified template arguments,
- // deduced template arguments. SFINAE applies unless we are in a lambda
- // body, see [temp.deduct]p9.
- case CodeSynthesisContext::ConstraintSubstitution:
- case CodeSynthesisContext::RequirementInstantiation:
- case CodeSynthesisContext::RequirementParameterInstantiation:
- // SFINAE always applies in a constraint expression or a requirement
- // in a requires expression.
- assert(Active->DeductionInfo && "Missing deduction info pointer");
- return Active->DeductionInfo;
-
- case CodeSynthesisContext::DeclaringSpecialMember:
- case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
- case CodeSynthesisContext::DefiningSynthesizedFunction:
- case CodeSynthesisContext::InitializingStructuredBinding:
- case CodeSynthesisContext::MarkingClassDllexported:
- case CodeSynthesisContext::BuildingBuiltinDumpStructCall:
- case CodeSynthesisContext::BuildingDeductionGuides:
- // This happens in a context unrelated to template instantiation, so
- // there is no SFINAE.
- return std::nullopt;
-
- case CodeSynthesisContext::ExceptionSpecEvaluation:
- // FIXME: This should not be treated as a SFINAE context, because
- // we will cache an incorrect exception specification. However, clang
- // bootstrap relies this! See PR31692.
- break;
-
- case CodeSynthesisContext::Memoization:
- break;
- }
-
- // The inner context was transparent for SFINAE. If it occurred within a
- // non-instantiation SFINAE context, then SFINAE applies.
- if (Active->SavedInNonInstantiationSFINAEContext)
- return std::optional<TemplateDeductionInfo *>(nullptr);
- }
-
- return std::nullopt;
-}
-
//===----------------------------------------------------------------------===/
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
@@ -2674,10 +2569,9 @@ ExprResult TemplateInstantiator::TransformRequiresTypeParams(
Sema::ExtParameterInfoBuilder &PInfos) {
TemplateDeductionInfo Info(KWLoc);
- Sema::InstantiatingTemplate TypeInst(SemaRef, KWLoc,
- RE, Info,
+ Sema::InstantiatingTemplate TypeInst(SemaRef, KWLoc, RE,
SourceRange{KWLoc, RBraceLoc});
- Sema::SFINAETrap Trap(SemaRef);
+ Sema::SFINAETrap Trap(SemaRef, Info);
unsigned ErrorIdx;
if (getDerived().TransformFunctionTypeParams(
@@ -2709,10 +2603,10 @@ TemplateInstantiator::TransformTypeRequirement(concepts::TypeRequirement *Req) {
return Req;
}
- Sema::SFINAETrap Trap(SemaRef);
TemplateDeductionInfo Info(Req->getType()->getTypeLoc().getBeginLoc());
- Sema::InstantiatingTemplate TypeInst(SemaRef,
- Req->getType()->getTypeLoc().getBeginLoc(), Req, Info,
+ Sema::SFINAETrap Trap(SemaRef, Info);
+ Sema::InstantiatingTemplate TypeInst(
+ SemaRef, Req->getType()->getTypeLoc().getBeginLoc(), Req,
Req->getType()->getTypeLoc().getSourceRange());
if (TypeInst.isInvalid())
return nullptr;
@@ -2730,8 +2624,6 @@ TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) {
if (!Req->isDependent() && !AlwaysRebuild())
return Req;
- Sema::SFINAETrap Trap(SemaRef);
-
llvm::PointerUnion<Expr *, concepts::Requirement::SubstitutionDiagnostic *>
TransExpr;
if (Req->isExprSubstitutionFailure())
@@ -2739,7 +2631,8 @@ TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) {
else {
Expr *E = Req->getExpr();
TemplateDeductionInfo Info(E->getBeginLoc());
- Sema::InstantiatingTemplate ExprInst(SemaRef, E->getBeginLoc(), Req, Info,
+ Sema::SFINAETrap Trap(SemaRef, Info);
+ Sema::InstantiatingTemplate ExprInst(SemaRef, E->getBeginLoc(), Req,
E->getSourceRange());
if (ExprInst.isInvalid())
return nullptr;
@@ -2765,8 +2658,9 @@ TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) {
TemplateParameterList *OrigTPL =
RetReq.getTypeConstraintTemplateParameterList();
TemplateDeductionInfo Info(OrigTPL->getTemplateLoc());
- Sema::InstantiatingTemplate TPLInst(SemaRef, OrigTPL->getTemplateLoc(),
- Req, Info, OrigTPL->getSourceRange());
+ Sema::SFINAETrap Trap(SemaRef, Info);
+ Sema::InstantiatingTemplate TPLInst(SemaRef, OrigTPL->getTemplateLoc(), Req,
+ OrigTPL->getSourceRange());
if (TPLInst.isInvalid())
return nullptr;
TemplateParameterList *TPL = TransformTemplateParameterList(OrigTPL);
@@ -2830,11 +2724,9 @@ TemplateInstantiator::TransformNestedRequirement(
bool Success;
Expr *NewConstraint;
- TemplateDeductionInfo Info(Constraint->getBeginLoc());
{
EnterExpressionEvaluationContext ContextRAII(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
-
Sema::InstantiatingTemplate ConstrInst(
SemaRef, Constraint->getBeginLoc(), Req,
Sema::InstantiatingTemplate::ConstraintsCheck(),
@@ -2843,16 +2735,10 @@ TemplateInstantiator::TransformNestedRequirement(
if (ConstrInst.isInvalid())
return nullptr;
- Sema::SFINAETrap Trap(SemaRef);
-
Success = !SemaRef.CheckConstraintSatisfaction(
Req, AssociatedConstraint(Constraint, SemaRef.ArgPackSubstIndex),
TemplateArgs, Constraint->getSourceRange(), Satisfaction,
/*TopLevelConceptId=*/nullptr, &NewConstraint);
-
- assert((!Success || !Trap.hasErrorOccurred()) &&
- "Substitution failures must be handled "
- "by CheckConstraintSatisfaction.");
}
if (!Success || Satisfaction.HasSubstitutionFailure())
@@ -3306,7 +3192,7 @@ bool Sema::SubstDefaultArgument(
EnterExpressionEvaluationContext EvalContext(
*this, ExpressionEvaluationContext::PotentiallyEvaluated, Param);
-
+ NonSFINAEContext _(*this);
InstantiatingTemplate Inst(*this, Loc, Param, TemplateArgs.getInnermost());
if (Inst.isInvalid())
return true;
@@ -3594,6 +3480,7 @@ bool Sema::InstantiateClassImpl(
Spec->setPointOfInstantiation(PointOfInstantiation);
}
+ NonSFINAEContext _(*this);
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
@@ -3828,6 +3715,7 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
MSInfo->setPointOfInstantiation(PointOfInstantiation);
}
+ NonSFINAEContext _(*this);
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
@@ -3892,6 +3780,7 @@ bool Sema::InstantiateInClassInitializer(
return true;
}
+ NonSFINAEContext _(*this);
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
@@ -3975,6 +3864,7 @@ static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
Sema &S, SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK, bool PrimaryStrictPackMatch) {
+ std::optional<Sema::NonSFINAEContext> NSC(S);
Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec);
if (Inst.isInvalid())
return {/*Invalid=*/true};
@@ -4076,6 +3966,7 @@ static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
if (Ambiguous) {
// Partial ordering did not produce a clear winner. Complain.
Inst.Clear();
+ NSC.reset();
S.Diag(PointOfInstantiation,
diag::err_partial_spec_ordering_ambiguous)
<< ClassTemplateSpec;
@@ -4507,6 +4398,7 @@ ExprResult Sema::SubstConceptTemplateArguments(
TemplateArgumentListInfo SubstArgs(ArgsAsWritten->getLAngleLoc(),
ArgsAsWritten->getRAngleLoc());
+ NonSFINAEContext _(*this);
Sema::InstantiatingTemplate Inst(
*this, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
Sema::InstantiatingTemplate::ConstraintNormalization{},
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 681bfe0..4d58f00 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5316,6 +5316,7 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
return;
}
+ NonSFINAEContext _(*this);
InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl,
InstantiatingTemplate::ExceptionSpecification());
if (Inst.isInvalid()) {
@@ -5383,6 +5384,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
if (isa<FunctionTemplateDecl>(ActiveInst.Entity)) {
+ SemaRef.CurrentSFINAEContext = nullptr;
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
ActiveInst.Entity = New;
@@ -5493,8 +5495,7 @@ FunctionDecl *Sema::InstantiateFunctionDeclaration(
SourceLocation Loc, CodeSynthesisContext::SynthesisKind CSC) {
FunctionDecl *FD = FTD->getTemplatedDecl();
- sema::TemplateDeductionInfo Info(Loc);
- InstantiatingTemplate Inst(*this, Loc, FTD, Args->asArray(), CSC, Info);
+ InstantiatingTemplate Inst(*this, Loc, FTD, Args->asArray(), CSC);
if (Inst.isInvalid())
return nullptr;
@@ -5684,6 +5685,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
}
}
+ NonSFINAEContext _(*this);
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
if (Inst.isInvalid())
return;
@@ -5974,6 +5976,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
if (FromVar->isInvalidDecl())
return nullptr;
+ NonSFINAEContext _(*this);
InstantiatingTemplate Inst(*this, PointOfInstantiation, FromVar);
if (Inst.isInvalid())
return nullptr;
@@ -6281,6 +6284,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
!Var->hasInit()) {
// FIXME: Factor out the duplicated instantiation context setup/tear down
// code here.
+ NonSFINAEContext _(*this);
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst.isInvalid())
return;
@@ -6385,6 +6389,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
return;
}
+ NonSFINAEContext _(*this);
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst.isInvalid())
return;
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 0f72d6a..5b1aad3 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -844,7 +844,7 @@ bool Sema::CheckParameterPacksForExpansion(
ArrayRef<UnexpandedParameterPack> Unexpanded,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool FailOnPackProducingTemplates, bool &ShouldExpand,
- bool &RetainExpansion, UnsignedOrNone &NumExpansions) {
+ bool &RetainExpansion, UnsignedOrNone &NumExpansions, bool Diagnose) {
ShouldExpand = true;
RetainExpansion = false;
IdentifierLoc FirstPack;
@@ -874,6 +874,9 @@ bool Sema::CheckParameterPacksForExpansion(
if (!FailOnPackProducingTemplates)
continue;
+ if (!Diagnose)
+ return true;
+
// It is not yet supported in certain contexts.
return Diag(PatternRange.getBegin().isValid() ? PatternRange.getBegin()
: EllipsisLoc,
@@ -1015,7 +1018,9 @@ bool Sema::CheckParameterPacksForExpansion(
// C++0x [temp.variadic]p5:
// All of the parameter packs expanded by a pack expansion shall have
// the same number of arguments specified.
- if (HaveFirstPack)
+ if (!Diagnose)
+ ;
+ else if (HaveFirstPack)
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
<< FirstPack.getIdentifierInfo() << Name << *NumExpansions
<< (LeastNewPackSize != NewPackSize) << LeastNewPackSize
@@ -1041,6 +1046,8 @@ bool Sema::CheckParameterPacksForExpansion(
if (NumExpansions && *NumExpansions < *NumPartialExpansions) {
NamedDecl *PartialPack =
CurrentInstantiationScope->getPartiallySubstitutedPack();
+ if (!Diagnose)
+ return true;
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial)
<< PartialPack << *NumPartialExpansions << *NumExpansions
<< SourceRange(PartiallySubstitutedPackLoc);
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index dffd7c1..c249148 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2463,6 +2463,19 @@ public:
LParenLoc, EndLoc);
}
+ /// Build a new OpenMP 'dyn_groupprivate' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPDynGroupprivateClause(
+ OpenMPDynGroupprivateClauseModifier M1,
+ OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
+ SourceLocation M2Loc, SourceLocation EndLoc) {
+ return getSema().OpenMP().ActOnOpenMPDynGroupprivateClause(
+ M1, M2, Size, StartLoc, LParenLoc, M1Loc, M2Loc, EndLoc);
+ }
+
/// Build a new OpenMP 'ompx_attribute' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@@ -8076,14 +8089,13 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
getSema().resetFPOptions(
S->getStoredFPFeatures().applyOverrides(getSema().getLangOpts()));
- const Stmt *ExprResult = S->getStmtExprResult();
bool SubStmtInvalid = false;
bool SubStmtChanged = false;
SmallVector<Stmt*, 8> Statements;
for (auto *B : S->body()) {
StmtResult Result = getDerived().TransformStmt(
- B, IsStmtExpr && B == ExprResult ? StmtDiscardKind::StmtExprResult
- : StmtDiscardKind::Discarded);
+ B, IsStmtExpr && B == S->body_back() ? StmtDiscardKind::StmtExprResult
+ : StmtDiscardKind::Discarded);
if (Result.isInvalid()) {
// Immediately fail if this was a DeclStmt, since it's very
@@ -11727,6 +11739,19 @@ OMPClause *TreeTransform<Derived>::TransformOMPXDynCGroupMemClause(
}
template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPDynGroupprivateClause(
+ OMPDynGroupprivateClause *C) {
+ ExprResult Size = getDerived().TransformExpr(C->getSize());
+ if (Size.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPDynGroupprivateClause(
+ C->getDynGroupprivateModifier(), C->getDynGroupprivateFallbackModifier(),
+ Size.get(), C->getBeginLoc(), C->getLParenLoc(),
+ C->getDynGroupprivateModifierLoc(),
+ C->getDynGroupprivateFallbackModifierLoc(), C->getEndLoc());
+}
+
+template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPDoacrossClause(OMPDoacrossClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
@@ -15824,16 +15849,20 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
Sema::ExpressionEvaluationContext::PotentiallyEvaluated,
E->getCallOperator());
- Sema::CodeSynthesisContext C;
- C.Kind = clang::Sema::CodeSynthesisContext::LambdaExpressionSubstitution;
- C.PointOfInstantiation = E->getBody()->getBeginLoc();
- getSema().pushCodeSynthesisContext(C);
+ StmtResult Body;
+ {
+ Sema::NonSFINAEContext _(getSema());
+ Sema::CodeSynthesisContext C;
+ C.Kind = clang::Sema::CodeSynthesisContext::LambdaExpressionSubstitution;
+ C.PointOfInstantiation = E->getBody()->getBeginLoc();
+ getSema().pushCodeSynthesisContext(C);
- // Instantiate the body of the lambda expression.
- StmtResult Body =
- Invalid ? StmtError() : getDerived().TransformLambdaBody(E, E->getBody());
+ // Instantiate the body of the lambda expression.
+ Body = Invalid ? StmtError()
+ : getDerived().TransformLambdaBody(E, E->getBody());
- getSema().popCodeSynthesisContext();
+ getSema().popCodeSynthesisContext();
+ }
// ActOnLambda* will pop the function scope for us.
FuncScopeCleanup.disable();
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index d552821..a04041c 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -11544,6 +11544,9 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_ompx_dyn_cgroup_mem:
C = new (Context) OMPXDynCGroupMemClause();
break;
+ case llvm::omp::OMPC_dyn_groupprivate:
+ C = new (Context) OMPDynGroupprivateClause();
+ break;
case llvm::omp::OMPC_doacross: {
unsigned NumVars = Record.readInt();
unsigned NumLoops = Record.readInt();
@@ -12736,6 +12739,19 @@ void OMPClauseReader::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) {
C->setLParenLoc(Record.readSourceLocation());
}
+void OMPClauseReader::VisitOMPDynGroupprivateClause(
+ OMPDynGroupprivateClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setDynGroupprivateModifier(
+ Record.readEnum<OpenMPDynGroupprivateClauseModifier>());
+ C->setDynGroupprivateFallbackModifier(
+ Record.readEnum<OpenMPDynGroupprivateClauseFallbackModifier>());
+ C->setSize(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setDynGroupprivateModifierLoc(Record.readSourceLocation());
+ C->setDynGroupprivateFallbackModifierLoc(Record.readSourceLocation());
+}
+
void OMPClauseReader::VisitOMPDoacrossClause(OMPDoacrossClause *C) {
C->setLParenLoc(Record.readSourceLocation());
C->setDependenceType(
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index b1fd151..821e7df 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -8651,6 +8651,17 @@ void OMPClauseWriter::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) {
Record.AddSourceLocation(C->getLParenLoc());
}
+void OMPClauseWriter::VisitOMPDynGroupprivateClause(
+ OMPDynGroupprivateClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.push_back(C->getDynGroupprivateModifier());
+ Record.push_back(C->getDynGroupprivateFallbackModifier());
+ Record.AddStmt(C->getSize());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getDynGroupprivateModifierLoc());
+ Record.AddSourceLocation(C->getDynGroupprivateFallbackModifierLoc());
+}
+
void OMPClauseWriter::VisitOMPDoacrossClause(OMPDoacrossClause *C) {
Record.push_back(C->varlist_size());
Record.push_back(C->getNumLoops());
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 63f0d70..0ba3c05 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -3254,9 +3254,6 @@ bool ConditionBRVisitor::printValue(const Expr *CondVarExpr, raw_ostream &Out,
return true;
}
-constexpr llvm::StringLiteral ConditionBRVisitor::GenericTrueMessage;
-constexpr llvm::StringLiteral ConditionBRVisitor::GenericFalseMessage;
-
bool ConditionBRVisitor::isPieceMessageGeneric(
const PathDiagnosticPiece *Piece) {
return Piece->getString() == GenericTrueMessage ||
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp
index eebecdb..4178d1f 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp
@@ -1,4 +1,4 @@
-//===- DependencyScanner.cpp - Performs module dependency scanning --------===//
+//===- DependencyScannerImpl.cpp - Implements module dependency scanning --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -12,6 +12,7 @@
#include "clang/Driver/Driver.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/TargetParser/Host.h"
using namespace clang;
@@ -456,7 +457,8 @@ initVFSForTUBuferScanning(IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
return std::make_pair(ModifiedFS, ModifiedCommandLine);
}
-std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::vector<std::string>>
+std::pair<IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>,
+ std::vector<std::string>>
initVFSForByNameScanning(IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
ArrayRef<std::string> CommandLine,
StringRef WorkingDirectory, StringRef ModuleName) {
@@ -588,7 +590,7 @@ computePrebuiltModulesASTMap(CompilerInstance &ScanInstance,
}
std::unique_ptr<DependencyOutputOptions>
-takeDependencyOutputOptionsFrom(CompilerInstance &ScanInstance) {
+takeAndUpdateDependencyOutputOptionsFrom(CompilerInstance &ScanInstance) {
// This function moves the existing dependency output options from the
// invocation to the collector. The options in the invocation are reset,
// which ensures that the compiler won't create new dependency collectors,
@@ -675,7 +677,7 @@ bool DependencyScanningAction::runInvocation(
if (!MaybePrebuiltModulesASTMap)
return false;
- auto DepOutputOpts = takeDependencyOutputOptionsFrom(ScanInstance);
+ auto DepOutputOpts = takeAndUpdateDependencyOutputOptionsFrom(ScanInstance);
MDC = initializeScanInstanceDependencyCollector(
ScanInstance, std::move(DepOutputOpts), WorkingDirectory, Consumer,
@@ -686,8 +688,6 @@ bool DependencyScanningAction::runInvocation(
if (Service.getFormat() == ScanningOutputFormat::P1689)
Action = std::make_unique<PreprocessOnlyAction>();
- else if (ModuleName)
- Action = std::make_unique<GetDependenciesByModuleNameAction>(*ModuleName);
else
Action = std::make_unique<ReadPCHAndPreprocessAction>();
@@ -704,3 +704,175 @@ bool DependencyScanningAction::runInvocation(
return Result;
}
+
+bool CompilerInstanceWithContext::initialize(DiagnosticConsumer *DC) {
+ if (DC) {
+ DiagConsumer = DC;
+ } else {
+ DiagPrinterWithOS =
+ std::make_unique<TextDiagnosticsPrinterWithOutput>(CommandLine);
+ DiagConsumer = &DiagPrinterWithOS->DiagPrinter;
+ }
+
+ std::tie(OverlayFS, CommandLine) = initVFSForByNameScanning(
+ Worker.BaseFS, CommandLine, CWD, "ScanningByName");
+
+ DiagEngineWithCmdAndOpts = std::make_unique<DignosticsEngineWithDiagOpts>(
+ CommandLine, OverlayFS, *DiagConsumer);
+
+ std::tie(Driver, Compilation) = buildCompilation(
+ CommandLine, *DiagEngineWithCmdAndOpts->DiagEngine, OverlayFS, Alloc);
+
+ if (!Compilation)
+ return false;
+
+ assert(Compilation->getJobs().size() &&
+ "Must have a job list of non-zero size");
+ const driver::Command &Command = *(Compilation->getJobs().begin());
+ const auto &CommandArgs = Command.getArguments();
+ assert(!CommandArgs.empty() && "Cannot have a command with 0 args");
+ assert(StringRef(CommandArgs[0]) == "-cc1" && "Requires a cc1 job.");
+ OriginalInvocation = std::make_unique<CompilerInvocation>();
+
+ if (!CompilerInvocation::CreateFromArgs(*OriginalInvocation, CommandArgs,
+ *DiagEngineWithCmdAndOpts->DiagEngine,
+ Command.getExecutable())) {
+ DiagEngineWithCmdAndOpts->DiagEngine->Report(
+ diag::err_fe_expected_compiler_job)
+ << llvm::join(CommandLine, " ");
+ return false;
+ }
+
+ if (any(Worker.Service.getOptimizeArgs() & ScanningOptimizations::Macros))
+ canonicalizeDefines(OriginalInvocation->getPreprocessorOpts());
+
+ // Create the CompilerInstance.
+ IntrusiveRefCntPtr<ModuleCache> ModCache =
+ makeInProcessModuleCache(Worker.Service.getModuleCacheEntries());
+ CIPtr = std::make_unique<CompilerInstance>(
+ std::make_shared<CompilerInvocation>(*OriginalInvocation),
+ Worker.PCHContainerOps, ModCache.get());
+ auto &CI = *CIPtr;
+
+ if (!initializeScanCompilerInstance(
+ CI, OverlayFS, DiagEngineWithCmdAndOpts->DiagEngine->getClient(),
+ Worker.Service, Worker.DepFS))
+ return false;
+
+ StableDirs = getInitialStableDirs(CI);
+ auto MaybePrebuiltModulesASTMap =
+ computePrebuiltModulesASTMap(CI, StableDirs);
+ if (!MaybePrebuiltModulesASTMap)
+ return false;
+
+ PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
+ OutputOpts = takeAndUpdateDependencyOutputOptionsFrom(CI);
+
+ // We do not create the target in initializeScanCompilerInstance because
+ // setting it here is unique for by-name lookups. We create the target only
+ // once here, and the information is reused for all computeDependencies calls.
+ // We do not need to call createTarget explicitly if we go through
+ // CompilerInstance::ExecuteAction to perform scanning.
+ CI.createTarget();
+
+ return true;
+}
+
+bool CompilerInstanceWithContext::computeDependencies(
+ StringRef ModuleName, DependencyConsumer &Consumer,
+ DependencyActionController &Controller) {
+ assert(CIPtr && "CIPtr must be initialized before calling this method");
+ auto &CI = *CIPtr;
+
+ // We create this cleanup object because computeDependencies may exit
+ // early with errors.
+ auto CleanUp = llvm::make_scope_exit([&]() {
+ CI.clearDependencyCollectors();
+ // The preprocessor may not be created at the entry of this method,
+ // but it must have been created when this method returns, whether
+ // there are errors during scanning or not.
+ CI.getPreprocessor().removePPCallbacks();
+ });
+
+ auto MDC = initializeScanInstanceDependencyCollector(
+ CI, std::make_unique<DependencyOutputOptions>(*OutputOpts), CWD, Consumer,
+ Worker.Service,
+ /* The MDC's constructor makes a copy of the OriginalInvocation, so
+ we can pass it in without worrying that it might be changed across
+ invocations of computeDependencies. */
+ *OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
+
+ if (!SrcLocOffset) {
+ // When SrcLocOffset is zero, we are at the beginning of the fake source
+ // file. In this case, we call BeginSourceFile to initialize.
+ std::unique_ptr<FrontendAction> Action =
+ std::make_unique<PreprocessOnlyAction>();
+ auto InputFile = CI.getFrontendOpts().Inputs.begin();
+ bool ActionBeginSucceeded = Action->BeginSourceFile(CI, *InputFile);
+ assert(ActionBeginSucceeded && "Action BeginSourceFile must succeed");
+ (void)ActionBeginSucceeded;
+ }
+
+ Preprocessor &PP = CI.getPreprocessor();
+ SourceManager &SM = PP.getSourceManager();
+ FileID MainFileID = SM.getMainFileID();
+ SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
+ SourceLocation IDLocation = FileStart.getLocWithOffset(SrcLocOffset);
+ PPCallbacks *CB = nullptr;
+ if (!SrcLocOffset) {
+ // We need to call EnterSourceFile when SrcLocOffset is zero to initialize
+ // the preprocessor.
+ bool PPFailed = PP.EnterSourceFile(MainFileID, nullptr, SourceLocation());
+ assert(!PPFailed && "Preprocess must be able to enter the main file.");
+ (void)PPFailed;
+ CB = MDC->getPPCallbacks();
+ } else {
+ // When SrcLocOffset is non-zero, the preprocessor has already been
+ // initialized through a previous call of computeDependencies. We want to
+ // preserve the PP's state, hence we do not call EnterSourceFile again.
+ MDC->attachToPreprocessor(PP);
+ CB = MDC->getPPCallbacks();
+
+ FileID PrevFID;
+ SrcMgr::CharacteristicKind FileType = SM.getFileCharacteristic(IDLocation);
+ CB->LexedFileChanged(MainFileID,
+ PPChainedCallbacks::LexedFileChangeReason::EnterFile,
+ FileType, PrevFID, IDLocation);
+ }
+
+ SrcLocOffset++;
+ SmallVector<IdentifierLoc, 2> Path;
+ IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
+ Path.emplace_back(IDLocation, ModuleID);
+ auto ModResult = CI.loadModule(IDLocation, Path, Module::Hidden, false);
+
+ assert(CB && "Must have PPCallbacks after module loading");
+ CB->moduleImport(SourceLocation(), Path, ModResult);
+ // Note that we are calling the CB's EndOfMainFile function, which
+ // forwards the results to the dependency consumer.
+ // It does not indicate the end of processing the fake file.
+ CB->EndOfMainFile();
+
+ if (!ModResult)
+ return false;
+
+ CompilerInvocation ModuleInvocation(*OriginalInvocation);
+ MDC->applyDiscoveredDependencies(ModuleInvocation);
+ Consumer.handleBuildCommand(
+ {CommandLine[0], ModuleInvocation.getCC1CommandLine()});
+
+ return true;
+}
+
+bool CompilerInstanceWithContext::finalize() {
+ DiagConsumer->finish();
+ return true;
+}
+
+llvm::Error CompilerInstanceWithContext::handleReturnStatus(bool Success) {
+ assert(DiagPrinterWithOS && "Must use the default DiagnosticConsumer.");
+ return Success ? llvm::Error::success()
+ : llvm::make_error<llvm::StringError>(
+ DiagPrinterWithOS->DiagnosticsOS.str(),
+ llvm::inconvertibleErrorCode());
+}
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h
index 5657317..54166da 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.h
@@ -1,4 +1,4 @@
-//===- DependencyScanner.h - Performs module dependency scanning *- C++ -*-===//
+//===- DependencyScannerImpl.h - Implements dependency scanning *- C++ -*--===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -23,6 +23,8 @@ class DiagnosticConsumer;
namespace tooling {
namespace dependencies {
class DependencyScanningService;
+class DependencyScanningWorker;
+
class DependencyConsumer;
class DependencyActionController;
class DependencyScanningWorkerFilesystem;
@@ -35,8 +37,7 @@ public:
IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS,
std::optional<StringRef> ModuleName = std::nullopt)
: Service(Service), WorkingDirectory(WorkingDirectory),
- Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)),
- ModuleName(ModuleName) {}
+ Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)) {}
bool runInvocation(std::unique_ptr<CompilerInvocation> Invocation,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
@@ -66,7 +67,6 @@ private:
DependencyConsumer &Consumer;
DependencyActionController &Controller;
IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
- std::optional<StringRef> ModuleName;
std::optional<CompilerInstance> ScanInstanceStorage;
std::shared_ptr<ModuleDepCollector> MDC;
std::vector<std::string> LastCC1Arguments;
@@ -118,7 +118,8 @@ initVFSForTUBuferScanning(IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
StringRef WorkingDirectory,
llvm::MemoryBufferRef TUBuffer);
-std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::vector<std::string>>
+std::pair<IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>,
+ std::vector<std::string>>
initVFSForByNameScanning(IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
ArrayRef<std::string> CommandLine,
StringRef WorkingDirectory, StringRef ModuleName);
@@ -137,7 +138,7 @@ computePrebuiltModulesASTMap(CompilerInstance &ScanInstance,
SmallVector<StringRef> &StableDirs);
std::unique_ptr<DependencyOutputOptions>
-takeDependencyOutputOptionsFrom(CompilerInstance &ScanInstance);
+takeAndUpdateDependencyOutputOptionsFrom(CompilerInstance &ScanInstance);
/// Create the dependency collector that will collect the produced
/// dependencies. May return the created ModuleDepCollector depending
@@ -150,6 +151,60 @@ std::shared_ptr<ModuleDepCollector> initializeScanInstanceDependencyCollector(
DependencyActionController &Controller,
PrebuiltModulesAttrsMap PrebuiltModulesASTMap,
llvm::SmallVector<StringRef> &StableDirs);
+
+class CompilerInstanceWithContext {
+ // Context
+ DependencyScanningWorker &Worker;
+ llvm::StringRef CWD;
+ std::vector<std::string> CommandLine;
+
+ // Context - file systems
+ llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS;
+
+ // Context - Diagnostics engine.
+ std::unique_ptr<TextDiagnosticsPrinterWithOutput> DiagPrinterWithOS;
+ // DiagConsumer may points to DiagPrinterWithOS->DiagPrinter, or a custom
+ // DiagnosticConsumer passed in from initialize.
+ DiagnosticConsumer *DiagConsumer = nullptr;
+ std::unique_ptr<DignosticsEngineWithDiagOpts> DiagEngineWithCmdAndOpts;
+
+ // Context - compiler invocation
+ // Compilation's command's arguments may be owned by Alloc when expanded from
+ // response files, so we need to keep Alloc alive in the context.
+ llvm::BumpPtrAllocator Alloc;
+ std::unique_ptr<clang::driver::Driver> Driver;
+ std::unique_ptr<clang::driver::Compilation> Compilation;
+ std::unique_ptr<CompilerInvocation> OriginalInvocation;
+
+ // Context - output options
+ std::unique_ptr<DependencyOutputOptions> OutputOpts;
+
+ // Context - stable directory handling
+ llvm::SmallVector<StringRef> StableDirs;
+ PrebuiltModulesAttrsMap PrebuiltModuleASTMap;
+
+ // Compiler Instance
+ std::unique_ptr<CompilerInstance> CIPtr;
+
+ // Source location offset.
+ int32_t SrcLocOffset = 0;
+
+public:
+ CompilerInstanceWithContext(DependencyScanningWorker &Worker, StringRef CWD,
+ const std::vector<std::string> &CMD)
+ : Worker(Worker), CWD(CWD), CommandLine(CMD) {};
+
+ // The three methods below returns false when they fail, with the detail
+ // accumulated in DiagConsumer.
+ bool initialize(DiagnosticConsumer *DC);
+ bool computeDependencies(StringRef ModuleName, DependencyConsumer &Consumer,
+ DependencyActionController &Controller);
+ bool finalize();
+
+ // The method below turns the return status from the above methods
+ // into an llvm::Error using a default DiagnosticConsumer.
+ llvm::Error handleReturnStatus(bool Success);
+};
} // namespace dependencies
} // namespace tooling
} // namespace clang
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
index 27734ff..a1f2db7 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
@@ -162,13 +162,45 @@ DependencyScanningTool::getModuleDependencies(
LookupModuleOutputCallback LookupModuleOutput) {
FullDependencyConsumer Consumer(AlreadySeen);
CallbackActionController Controller(LookupModuleOutput);
- llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer,
- Controller, ModuleName);
+ if (auto Error =
+ Worker.initializeCompilerInstanceWithContextOrError(CWD, CommandLine))
+ return std::move(Error);
+
+ auto Result = Worker.computeDependenciesByNameWithContextOrError(
+ ModuleName, Consumer, Controller);
+
+ if (auto Error = Worker.finalizeCompilerInstanceWithContextOrError())
+ return std::move(Error);
+
if (Result)
return std::move(Result);
+
return Consumer.takeTranslationUnitDeps();
}
+llvm::Error DependencyScanningTool::initializeCompilerInstanceWithContext(
+ StringRef CWD, const std::vector<std::string> &CommandLine) {
+ return Worker.initializeCompilerInstanceWithContextOrError(CWD, CommandLine);
+}
+
+llvm::Expected<TranslationUnitDeps>
+DependencyScanningTool::computeDependenciesByNameWithContext(
+ StringRef ModuleName, const llvm::DenseSet<ModuleID> &AlreadySeen,
+ LookupModuleOutputCallback LookupModuleOutput) {
+ FullDependencyConsumer Consumer(AlreadySeen);
+ CallbackActionController Controller(LookupModuleOutput);
+ llvm::Error Result = Worker.computeDependenciesByNameWithContextOrError(
+ ModuleName, Consumer, Controller);
+ if (Result)
+ return std::move(Result);
+
+ return Consumer.takeTranslationUnitDeps();
+}
+
+llvm::Error DependencyScanningTool::finalizeCompilerInstanceWithContext() {
+ return Worker.finalizeCompilerInstanceWithContextOrError();
+}
+
TranslationUnitDeps FullDependencyConsumer::takeTranslationUnitDeps() {
TranslationUnitDeps TU;
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 0a1cf6b..dc408b1 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -43,6 +43,9 @@ DependencyScanningWorker::DependencyScanningWorker(
}
}
+DependencyScanningWorker::~DependencyScanningWorker() = default;
+DependencyActionController::~DependencyActionController() = default;
+
llvm::Error DependencyScanningWorker::computeDependencies(
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer, DependencyActionController &Controller,
@@ -58,21 +61,6 @@ llvm::Error DependencyScanningWorker::computeDependencies(
DiagPrinterWithOS.DiagnosticsOS.str(), llvm::inconvertibleErrorCode());
}
-llvm::Error DependencyScanningWorker::computeDependencies(
- StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
- DependencyConsumer &Consumer, DependencyActionController &Controller,
- StringRef ModuleName) {
- // Capture the emitted diagnostics and report them to the client
- // in the case of a failure.
- TextDiagnosticsPrinterWithOutput DiagPrinterWithOS(CommandLine);
-
- if (computeDependencies(WorkingDirectory, CommandLine, Consumer, Controller,
- DiagPrinterWithOS.DiagPrinter, ModuleName))
- return llvm::Error::success();
- return llvm::make_error<llvm::StringError>(
- DiagPrinterWithOS.DiagnosticsOS.str(), llvm::inconvertibleErrorCode());
-}
-
static bool forEachDriverJob(
ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
@@ -113,11 +101,11 @@ static bool createAndRunToolInvocation(
bool DependencyScanningWorker::scanDependencies(
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer, DependencyActionController &Controller,
- DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
- std::optional<StringRef> ModuleName) {
+ DiagnosticConsumer &DC,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
DignosticsEngineWithDiagOpts DiagEngineWithCmdAndOpts(CommandLine, FS, DC);
DependencyScanningAction Action(Service, WorkingDirectory, Consumer,
- Controller, DepFS, ModuleName);
+ Controller, DepFS);
bool Success = false;
if (CommandLine[1] == "-cc1") {
@@ -172,24 +160,51 @@ bool DependencyScanningWorker::computeDependencies(
auto [FinalFS, FinalCommandLine] = initVFSForTUBuferScanning(
BaseFS, CommandLine, WorkingDirectory, *TUBuffer);
return scanDependencies(WorkingDirectory, FinalCommandLine, Consumer,
- Controller, DC, FinalFS,
- /*ModuleName=*/std::nullopt);
+ Controller, DC, FinalFS);
} else {
BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
return scanDependencies(WorkingDirectory, CommandLine, Consumer, Controller,
- DC, BaseFS, /*ModuleName=*/std::nullopt);
+ DC, BaseFS);
}
}
-bool DependencyScanningWorker::computeDependencies(
- StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
- DependencyConsumer &Consumer, DependencyActionController &Controller,
- DiagnosticConsumer &DC, StringRef ModuleName) {
- auto [OverlayFS, ModifiedCommandLine] = initVFSForByNameScanning(
- BaseFS, CommandLine, WorkingDirectory, ModuleName);
+llvm::Error
+DependencyScanningWorker::initializeCompilerInstanceWithContextOrError(
+ StringRef CWD, const std::vector<std::string> &CommandLine) {
+ bool Success = initializeCompilerInstanceWithContext(CWD, CommandLine);
+ return CIWithContext->handleReturnStatus(Success);
+}
+
+llvm::Error
+DependencyScanningWorker::computeDependenciesByNameWithContextOrError(
+ StringRef ModuleName, DependencyConsumer &Consumer,
+ DependencyActionController &Controller) {
+ bool Success =
+ computeDependenciesByNameWithContext(ModuleName, Consumer, Controller);
+ return CIWithContext->handleReturnStatus(Success);
+}
+
+llvm::Error
+DependencyScanningWorker::finalizeCompilerInstanceWithContextOrError() {
+ bool Success = finalizeCompilerInstance();
+ return CIWithContext->handleReturnStatus(Success);
+}
- return scanDependencies(WorkingDirectory, ModifiedCommandLine, Consumer,
- Controller, DC, OverlayFS, ModuleName);
+bool DependencyScanningWorker::initializeCompilerInstanceWithContext(
+ StringRef CWD, const std::vector<std::string> &CommandLine,
+ DiagnosticConsumer *DC) {
+ CIWithContext =
+ std::make_unique<CompilerInstanceWithContext>(*this, CWD, CommandLine);
+ return CIWithContext->initialize(DC);
}
-DependencyActionController::~DependencyActionController() {}
+bool DependencyScanningWorker::computeDependenciesByNameWithContext(
+ StringRef ModuleName, DependencyConsumer &Consumer,
+ DependencyActionController &Controller) {
+ assert(CIWithContext && "CompilerInstance with context required!");
+ return CIWithContext->computeDependencies(ModuleName, Consumer, Controller);
+}
+
+bool DependencyScanningWorker::finalizeCompilerInstance() {
+ return CIWithContext->finalize();
+}
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index a117bec..e07a208 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -965,7 +965,9 @@ ModuleDepCollector::ModuleDepCollector(
makeCommonInvocationForModuleBuild(std::move(OriginalCI))) {}
void ModuleDepCollector::attachToPreprocessor(Preprocessor &PP) {
- PP.addPPCallbacks(std::make_unique<ModuleDepCollectorPP>(*this));
+ auto CollectorPP = std::make_unique<ModuleDepCollectorPP>(*this);
+ CollectorPPPtr = CollectorPP.get();
+ PP.addPPCallbacks(std::move(CollectorPP));
}
void ModuleDepCollector::attachToASTReader(ASTReader &R) {}
diff --git a/clang/lib/Tooling/Syntax/TokenBufferTokenManager.cpp b/clang/lib/Tooling/Syntax/TokenBufferTokenManager.cpp
index a06f7e2..3d63d4a 100644
--- a/clang/lib/Tooling/Syntax/TokenBufferTokenManager.cpp
+++ b/clang/lib/Tooling/Syntax/TokenBufferTokenManager.cpp
@@ -10,8 +10,6 @@
namespace clang {
namespace syntax {
-constexpr llvm::StringLiteral syntax::TokenBufferTokenManager::Kind;
-
std::pair<FileID, ArrayRef<syntax::Token>>
syntax::TokenBufferTokenManager::lexBuffer(
std::unique_ptr<llvm::MemoryBuffer> Input) {