summaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp10
-rw-r--r--lib/Sema/SemaCoroutine.cpp13
-rw-r--r--lib/Sema/SemaDecl.cpp96
-rw-r--r--lib/Sema/SemaDeclObjC.cpp6
-rw-r--r--lib/Sema/SemaExprCXX.cpp14
-rw-r--r--lib/Sema/SemaOpenMP.cpp97
-rw-r--r--lib/Sema/SemaOverload.cpp60
-rw-r--r--lib/Sema/SemaStmt.cpp9
-rw-r--r--lib/Sema/SemaTemplate.cpp72
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp3
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp13
-rw-r--r--lib/Sema/SemaType.cpp2
-rw-r--r--lib/Sema/TreeTransform.h13
13 files changed, 232 insertions, 176 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 5953d020b4fb..a987a8ce0b31 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -56,6 +56,8 @@ using namespace clang;
namespace {
class UnreachableCodeHandler : public reachable_code::Callback {
Sema &S;
+ SourceRange PreviousSilenceableCondVal;
+
public:
UnreachableCodeHandler(Sema &s) : S(s) {}
@@ -64,6 +66,14 @@ namespace {
SourceRange SilenceableCondVal,
SourceRange R1,
SourceRange R2) override {
+ // Avoid reporting multiple unreachable code diagnostics that are
+ // triggered by the same conditional value.
+ if (PreviousSilenceableCondVal.isValid() &&
+ SilenceableCondVal.isValid() &&
+ PreviousSilenceableCondVal == SilenceableCondVal)
+ return;
+ PreviousSilenceableCondVal = SilenceableCondVal;
+
unsigned diag = diag::warn_unreachable;
switch (UK) {
case reachable_code::UK_Break:
diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp
index 3109358df464..9814b4a84f29 100644
--- a/lib/Sema/SemaCoroutine.cpp
+++ b/lib/Sema/SemaCoroutine.cpp
@@ -187,7 +187,7 @@ static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise);
if (!ScopeInfo->CoroutinePromise->isInvalidDecl())
- S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise, false);
+ S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise);
}
return ScopeInfo;
@@ -578,17 +578,6 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
isa<CoyieldExpr>(First) ? 1 : 2);
}
- bool AnyCoawaits = false;
- bool AnyCoyields = false;
- for (auto *CoroutineStmt : Fn->CoroutineStmts) {
- AnyCoawaits |= isa<CoawaitExpr>(CoroutineStmt);
- AnyCoyields |= isa<CoyieldExpr>(CoroutineStmt);
- }
-
- if (!AnyCoawaits && !AnyCoyields)
- Diag(Fn->CoroutineStmts.front()->getLocStart(),
- diag::ext_coroutine_without_co_await_co_yield);
-
SourceLocation Loc = FD->getLocation();
// Form a declaration statement for the promise declaration, so that AST
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c32757565dd1..adcf2ee00e75 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1044,7 +1044,8 @@ Corrected:
}
// We can have a type template here if we're classifying a template argument.
- if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl))
+ if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl) &&
+ !isa<VarTemplateDecl>(FirstDecl))
return NameClassification::TypeTemplate(
TemplateName(cast<TemplateDecl>(FirstDecl)));
@@ -4503,7 +4504,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// trivial in almost all cases, except if a union member has an in-class
// initializer:
// union { int n = 0; };
- ActOnUninitializedDecl(Anon, /*TypeMayContainAuto=*/false);
+ ActOnUninitializedDecl(Anon);
}
Anon->setImplicit();
@@ -6425,9 +6426,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
- // Diagnose shadowed variables before filtering for scope.
- if (D.getCXXScopeSpec().isEmpty())
- CheckShadow(S, NewVD, Previous);
+ // Find the shadowed declaration before filtering for scope.
+ NamedDecl *ShadowedDecl = D.getCXXScopeSpec().isEmpty()
+ ? getShadowedDeclaration(NewVD, Previous)
+ : nullptr;
// Don't consider existing declarations that are in a different
// scope and are out-of-semantic-context declarations (if the new
@@ -6522,6 +6524,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
+ // Diagnose shadowed variables iff this isn't a redeclaration.
+ if (ShadowedDecl && !D.isRedeclaration())
+ CheckShadow(NewVD, ShadowedDecl, Previous);
+
ProcessPragmaWeak(S, NewVD);
// If this is the first declaration of an extern C variable, update
@@ -6595,33 +6601,40 @@ static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI,
return SourceLocation();
}
-/// \brief Diagnose variable or built-in function shadowing. Implements
-/// -Wshadow.
-///
-/// This method is called whenever a VarDecl is added to a "useful"
-/// scope.
-///
-/// \param S the scope in which the shadowing name is being declared
-/// \param R the lookup of the name
-///
-void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
+/// \brief Return the declaration shadowed by the given variable \p D, or null
+/// if it doesn't shadow any declaration or shadowing warnings are disabled.
+NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D,
+ const LookupResult &R) {
// Return if warning is ignored.
if (Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc()))
- return;
+ return nullptr;
// Don't diagnose declarations at file scope.
if (D->hasGlobalStorage())
- return;
-
- DeclContext *NewDC = D->getDeclContext();
+ return nullptr;
// Only diagnose if we're shadowing an unambiguous field or variable.
if (R.getResultKind() != LookupResult::Found)
- return;
+ return nullptr;
- NamedDecl* ShadowedDecl = R.getFoundDecl();
- if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl))
- return;
+ NamedDecl *ShadowedDecl = R.getFoundDecl();
+ return isa<VarDecl>(ShadowedDecl) || isa<FieldDecl>(ShadowedDecl)
+ ? ShadowedDecl
+ : nullptr;
+}
+
+/// \brief Diagnose variable or built-in function shadowing. Implements
+/// -Wshadow.
+///
+/// This method is called whenever a VarDecl is added to a "useful"
+/// scope.
+///
+/// \param ShadowedDecl the declaration that is shadowed by the given variable
+/// \param R the lookup of the name
+///
+void Sema::CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl,
+ const LookupResult &R) {
+ DeclContext *NewDC = D->getDeclContext();
if (FieldDecl *FD = dyn_cast<FieldDecl>(ShadowedDecl)) {
// Fields are not shadowed by variables in C++ static methods.
@@ -6732,7 +6745,8 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) {
LookupResult R(*this, D->getDeclName(), D->getLocation(),
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
LookupName(R, S);
- CheckShadow(S, D, R);
+ if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R))
+ CheckShadow(D, ShadowedDecl, R);
}
/// Check if 'E', which is an expression that is about to be modified, refers
@@ -9782,8 +9796,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
/// AddInitializerToDecl - Adds the initializer Init to the
/// declaration dcl. If DirectInit is true, this is C++ direct
/// initialization rather than copy initialization.
-void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
- bool DirectInit, bool TypeMayContainAuto) {
+void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
if (!RealDecl || RealDecl->isInvalidDecl()) {
@@ -9808,7 +9821,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
}
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
- if (TypeMayContainAuto && VDecl->getType()->isUndeducedType()) {
+ if (VDecl->getType()->isUndeducedType()) {
// Attempt typo correction early so that the type of the init expression can
// be deduced based on the chosen correction if the original init contains a
// TypoExpr.
@@ -10280,8 +10293,7 @@ bool Sema::canInitializeWithParenthesizedList(QualType TargetType) {
TargetType->getContainedAutoType();
}
-void Sema::ActOnUninitializedDecl(Decl *RealDecl,
- bool TypeMayContainAuto) {
+void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
// If there is no declaration, there was an error parsing it. Just ignore it.
if (!RealDecl)
return;
@@ -10297,7 +10309,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
}
// C++11 [dcl.spec.auto]p3
- if (TypeMayContainAuto && Type->getContainedAutoType()) {
+ if (Type->isUndeducedType()) {
Diag(Var->getLocation(), diag::err_auto_var_requires_init)
<< Var->getDeclName() << Type;
Var->setInvalidDecl();
@@ -11081,32 +11093,32 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
}
}
- return BuildDeclaratorGroup(Decls, DS.containsPlaceholderType());
+ return BuildDeclaratorGroup(Decls);
}
/// BuildDeclaratorGroup - convert a list of declarations into a declaration
/// group, performing any necessary semantic checking.
Sema::DeclGroupPtrTy
-Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group,
- bool TypeMayContainAuto) {
- // C++0x [dcl.spec.auto]p7:
- // If the type deduced for the template parameter U is not the same in each
+Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group) {
+ // C++14 [dcl.spec.auto]p7: (DR1347)
+ // If the type that replaces the placeholder type is not the same in each
// deduction, the program is ill-formed.
- // FIXME: When initializer-list support is added, a distinction is needed
- // between the deduced type U and the deduced type which 'auto' stands for.
- // auto a = 0, b = { 1, 2, 3 };
- // is legal because the deduced type U is 'int' in both cases.
- if (TypeMayContainAuto && Group.size() > 1) {
+ if (Group.size() > 1) {
QualType Deduced;
CanQualType DeducedCanon;
VarDecl *DeducedDecl = nullptr;
for (unsigned i = 0, e = Group.size(); i != e; ++i) {
if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) {
AutoType *AT = D->getType()->getContainedAutoType();
+ // FIXME: DR1265: if we have a function pointer declaration, we can have
+ // an 'auto' from a trailing return type. In that case, the return type
+ // must match the various other uses of 'auto'.
+ if (!AT)
+ continue;
// Don't reissue diagnostics when instantiating a template.
- if (AT && D->isInvalidDecl())
+ if (D->isInvalidDecl())
break;
- QualType U = AT ? AT->getDeducedType() : QualType();
+ QualType U = AT->getDeducedType();
if (!U.isNull()) {
CanQualType UCanon = Context.getCanonicalType(U);
if (Deduced.isNull()) {
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index d172c951e749..b43e5b9e3278 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1712,7 +1712,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
DeclsInGroup.push_back(PDecl);
}
- return BuildDeclaratorGroup(DeclsInGroup, false);
+ return BuildDeclaratorGroup(DeclsInGroup);
}
Decl *Sema::
@@ -2019,7 +2019,7 @@ Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef<Decl *> Decls) {
DeclsInGroup.push_back(ObjCImpDecl);
- return BuildDeclaratorGroup(DeclsInGroup, false);
+ return BuildDeclaratorGroup(DeclsInGroup);
}
void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
@@ -3043,7 +3043,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
DeclsInGroup.push_back(IDecl);
}
- return BuildDeclaratorGroup(DeclsInGroup, false);
+ return BuildDeclaratorGroup(DeclsInGroup);
}
static bool tryMatchRecordTypes(ASTContext &Context,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 1379440e8a03..b2fb33f53432 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1504,14 +1504,12 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
SourceLocation PlacementRParen, SourceRange TypeIdParens,
Declarator &D, Expr *Initializer) {
- bool TypeContainsAuto = D.getDeclSpec().containsPlaceholderType();
-
Expr *ArraySize = nullptr;
// If the specified type is an array, unwrap it and save the expression.
if (D.getNumTypeObjects() > 0 &&
D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
- DeclaratorChunk &Chunk = D.getTypeObject(0);
- if (TypeContainsAuto)
+ DeclaratorChunk &Chunk = D.getTypeObject(0);
+ if (D.getDeclSpec().containsPlaceholderType())
return ExprError(Diag(Chunk.Loc, diag::err_new_array_of_auto)
<< D.getSourceRange());
if (Chunk.Arr.hasStatic)
@@ -1588,8 +1586,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
TInfo,
ArraySize,
DirectInitRange,
- Initializer,
- TypeContainsAuto);
+ Initializer);
}
static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style,
@@ -1621,8 +1618,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
TypeSourceInfo *AllocTypeInfo,
Expr *ArraySize,
SourceRange DirectInitRange,
- Expr *Initializer,
- bool TypeMayContainAuto) {
+ Expr *Initializer) {
SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange();
SourceLocation StartLoc = Range.getBegin();
@@ -1648,7 +1644,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
}
// C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
- if (TypeMayContainAuto && AllocType->isUndeducedType()) {
+ if (AllocType->isUndeducedType()) {
if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
<< AllocType << TypeRange);
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index edceb537df75..dcd19c8d817d 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -1089,7 +1089,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
auto *VDPrivate = buildVarDecl(
*this, DE->getExprLoc(), Type.getUnqualifiedType(),
VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr);
- ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
+ ActOnUninitializedDecl(VDPrivate);
if (VDPrivate->isInvalidDecl())
continue;
PrivateCopies.push_back(buildDeclRefExpr(
@@ -1701,7 +1701,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_teams_distribute_parallel_for:
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_parallel_for:
- case OMPD_target_teams_distribute_parallel_for_simd: {
+ case OMPD_target_teams_distribute_parallel_for_simd:
+ case OMPD_target_teams_distribute_simd: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
@@ -1761,8 +1762,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
if (!WithInit)
CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C, SourceRange()));
S.CurContext->addHiddenDecl(CED);
- S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false,
- /*TypeMayContainAuto=*/true);
+ S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
return CED;
}
@@ -2446,6 +2446,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
AllowedNameModifiers.push_back(OMPD_target);
AllowedNameModifiers.push_back(OMPD_parallel);
break;
+ case OMPD_target_teams_distribute_simd:
+ Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
+ ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_target);
+ break;
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_threadprivate:
@@ -3970,33 +3975,32 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Lower bound variable, initialized with zero.
VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
- SemaRef.AddInitializerToDecl(
- LBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
- /*DirectInit*/ false, /*TypeMayContainAuto*/ false);
+ SemaRef.AddInitializerToDecl(LBDecl,
+ SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
+ /*DirectInit*/ false);
// Upper bound variable, initialized with last iteration number.
VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
- /*DirectInit*/ false,
- /*TypeMayContainAuto*/ false);
+ /*DirectInit*/ false);
// A 32-bit variable-flag where runtime returns 1 for the last iteration.
// This will be used to implement clause 'lastprivate'.
QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
- SemaRef.AddInitializerToDecl(
- ILDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
- /*DirectInit*/ false, /*TypeMayContainAuto*/ false);
+ SemaRef.AddInitializerToDecl(ILDecl,
+ SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
+ /*DirectInit*/ false);
// Stride variable returned by runtime (we initialize it to 1 by default).
VarDecl *STDecl =
buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
- SemaRef.AddInitializerToDecl(
- STDecl, SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
- /*DirectInit*/ false, /*TypeMayContainAuto*/ false);
+ SemaRef.AddInitializerToDecl(STDecl,
+ SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
+ /*DirectInit*/ false);
// Build expression: UB = min(UB, LastIteration)
// It is necessary for CodeGen of directives with static scheduling.
@@ -6428,6 +6432,39 @@ StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
+StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ auto *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' with number of loops, it will
+ // define the nested loops number.
+ auto NestedLoopCount = CheckOpenMPLoop(
+ OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp target teams distribute simd loop exprs were not built");
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPTargetTeamsDistributeSimdDirective::Create(
+ Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
+}
+
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -7448,10 +7485,13 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// A list item cannot appear in both a map clause and a data-sharing
// attribute clause on the same construct
if (CurrDir == OMPD_target || CurrDir == OMPD_target_parallel ||
- CurrDir == OMPD_target_teams ||
+ CurrDir == OMPD_target_teams ||
CurrDir == OMPD_target_teams_distribute ||
CurrDir == OMPD_target_teams_distribute_parallel_for ||
- CurrDir == OMPD_target_teams_distribute_parallel_for_simd) {
+ CurrDir == OMPD_target_teams_distribute_parallel_for_simd ||
+ CurrDir == OMPD_target_teams_distribute_simd ||
+ CurrDir == OMPD_target_parallel_for_simd ||
+ CurrDir == OMPD_target_parallel_for) {
OpenMPClauseKind ConflictKind;
if (DSAStack->checkMappableExprComponentListsForDecl(
VD, /*CurrentRegionOnly=*/true,
@@ -7481,7 +7521,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
Type = Type.getUnqualifiedType();
auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
D->hasAttrs() ? &D->getAttrs() : nullptr);
- ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
+ ActOnUninitializedDecl(VDPrivate);
if (VDPrivate->isInvalidDecl())
continue;
auto VDPrivateRefExpr = buildDeclRefExpr(
@@ -7709,10 +7749,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// A list item cannot appear in both a map clause and a data-sharing
// attribute clause on the same construct
if (CurrDir == OMPD_target || CurrDir == OMPD_target_parallel ||
- CurrDir == OMPD_target_teams ||
+ CurrDir == OMPD_target_teams ||
CurrDir == OMPD_target_teams_distribute ||
CurrDir == OMPD_target_teams_distribute_parallel_for ||
- CurrDir == OMPD_target_teams_distribute_parallel_for_simd) {
+ CurrDir == OMPD_target_teams_distribute_parallel_for_simd ||
+ CurrDir == OMPD_target_teams_distribute_simd ||
+ CurrDir == OMPD_target_parallel_for_simd ||
+ CurrDir == OMPD_target_parallel_for) {
OpenMPClauseKind ConflictKind;
if (DSAStack->checkMappableExprComponentListsForDecl(
VD, /*CurrentRegionOnly=*/true,
@@ -7784,7 +7827,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
RefExpr->getExprLoc());
AddInitializerToDecl(VDPrivate,
DefaultLvalueConversion(VDInitRefExpr).get(),
- /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
+ /*DirectInit=*/false);
}
if (VDPrivate->isInvalidDecl()) {
if (IsImplicitClause) {
@@ -8634,10 +8677,9 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
}
}
if (Init && DeclareReductionRef.isUnset()) {
- AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false,
- /*TypeMayContainAuto=*/false);
+ AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
} else if (!Init)
- ActOnUninitializedDecl(RHSVD, /*TypeMayContainAuto=*/false);
+ ActOnUninitializedDecl(RHSVD);
if (RHSVD->isInvalidDecl())
continue;
if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
@@ -8886,7 +8928,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
else
InitExpr = VD ? SimpleRefExpr : Ref;
AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
- /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
+ /*DirectInit=*/false);
auto InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
@@ -10231,7 +10273,8 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
if ((DKind == OMPD_target || DKind == OMPD_target_teams ||
DKind == OMPD_target_teams_distribute ||
DKind == OMPD_target_teams_distribute_parallel_for ||
- DKind == OMPD_target_teams_distribute_parallel_for_simd) && VD) {
+ DKind == OMPD_target_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_target_teams_distribute_simd) && VD) {
auto DVar = DSAS->getTopDSA(VD, false);
if (isOpenMPPrivate(DVar.CKind)) {
SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
@@ -10963,7 +11006,7 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
RefExpr->getExprLoc());
AddInitializerToDecl(VDPrivate,
DefaultLvalueConversion(VDInitRefExpr).get(),
- /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
+ /*DirectInit=*/false);
// If required, build a capture to implement the privatization initialized
// with the current list item value.
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 41f4fa746fc6..afdae4ed6d7d 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -6596,7 +6596,9 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
Candidate.Function = MethodTmpl->getTemplatedDecl();
Candidate.Viable = false;
Candidate.IsSurrogate = false;
- Candidate.IgnoreObjectArgument = false;
+ Candidate.IgnoreObjectArgument =
+ cast<CXXMethodDecl>(Candidate.Function)->isStatic() ||
+ ObjectType.isNull();
Candidate.ExplicitCallArguments = Args.size();
if (Result == TDK_NonDependentConversionFailure)
Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -6658,7 +6660,11 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
Candidate.Function = FunctionTemplate->getTemplatedDecl();
Candidate.Viable = false;
Candidate.IsSurrogate = false;
- Candidate.IgnoreObjectArgument = false;
+ // Ignore the object argument if there is one, since we don't have an object
+ // type.
+ Candidate.IgnoreObjectArgument =
+ isa<CXXMethodDecl>(Candidate.Function) &&
+ !isa<CXXConstructorDecl>(Candidate.Function);
Candidate.ExplicitCallArguments = Args.size();
if (Result == TDK_NonDependentConversionFailure)
Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -10490,56 +10496,42 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
// operation somehow.
bool SuppressUserConversions = false;
- const FunctionProtoType *Proto;
- unsigned ArgIdx = 0;
+ unsigned ConvIdx = 0;
+ ArrayRef<QualType> ParamTypes;
if (Cand->IsSurrogate) {
QualType ConvType
= Cand->Surrogate->getConversionType().getNonReferenceType();
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
ConvType = ConvPtrType->getPointeeType();
- Proto = ConvType->getAs<FunctionProtoType>();
- ArgIdx = 1;
+ ParamTypes = ConvType->getAs<FunctionProtoType>()->getParamTypes();
+ // Conversion 0 is 'this', which doesn't have a corresponding argument.
+ ConvIdx = 1;
} else if (Cand->Function) {
- Proto = Cand->Function->getType()->getAs<FunctionProtoType>();
+ ParamTypes =
+ Cand->Function->getType()->getAs<FunctionProtoType>()->getParamTypes();
if (isa<CXXMethodDecl>(Cand->Function) &&
- !isa<CXXConstructorDecl>(Cand->Function))
- ArgIdx = 1;
+ !isa<CXXConstructorDecl>(Cand->Function)) {
+ // Conversion 0 is 'this', which doesn't have a corresponding argument.
+ ConvIdx = 1;
+ }
} else {
- // Builtin binary operator with a bad first conversion.
+ // Builtin operator.
assert(ConvCount <= 3);
- for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
- ConvIdx != ConvCount; ++ConvIdx) {
- if (Cand->Conversions[ConvIdx].isInitialized())
- continue;
- if (Cand->BuiltinTypes.ParamTypes[ConvIdx]->isDependentType())
- Cand->Conversions[ConvIdx].setAsIdentityConversion(
- Args[ConvIdx]->getType());
- else
- Cand->Conversions[ConvIdx] = TryCopyInitialization(
- S, Args[ConvIdx], Cand->BuiltinTypes.ParamTypes[ConvIdx],
- SuppressUserConversions,
- /*InOverloadResolution*/ true,
- /*AllowObjCWritebackConversion=*/
- S.getLangOpts().ObjCAutoRefCount);
- // FIXME: If the conversion is bad, try to fix it.
- }
- return;
+ ParamTypes = Cand->BuiltinTypes.ParamTypes;
}
// Fill in the rest of the conversions.
- unsigned NumParams = Proto->getNumParams();
- for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
- ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
+ for (unsigned ArgIdx = 0; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
if (Cand->Conversions[ConvIdx].isInitialized()) {
- // Found the bad conversion.
- } else if (ArgIdx < NumParams) {
- if (Proto->getParamType(ArgIdx)->isDependentType())
+ // We've already checked this conversion.
+ } else if (ArgIdx < ParamTypes.size()) {
+ if (ParamTypes[ArgIdx]->isDependentType())
Cand->Conversions[ConvIdx].setAsIdentityConversion(
Args[ArgIdx]->getType());
else {
Cand->Conversions[ConvIdx] =
- TryCopyInitialization(S, Args[ArgIdx], Proto->getParamType(ArgIdx),
+ TryCopyInitialization(S, Args[ArgIdx], ParamTypes[ArgIdx],
SuppressUserConversions,
/*InOverloadResolution=*/true,
/*AllowObjCWritebackConversion=*/
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 50f0a22ff02b..a8832e9a1c54 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -1881,8 +1881,7 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
SemaRef.inferObjCARCLifetime(Decl))
Decl->setInvalidDecl();
- SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false,
- /*TypeMayContainAuto=*/false);
+ SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false);
SemaRef.FinalizeDeclaration(Decl);
SemaRef.CurContext->addHiddenDecl(Decl);
return false;
@@ -2005,8 +2004,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
// Claim the type doesn't contain auto: we've already done the checking.
DeclGroupPtrTy RangeGroup =
- BuildDeclaratorGroup(MutableArrayRef<Decl *>((Decl **)&RangeVar, 1),
- /*TypeMayContainAuto=*/ false);
+ BuildDeclaratorGroup(MutableArrayRef<Decl *>((Decl **)&RangeVar, 1));
StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc);
if (RangeDecl.isInvalid()) {
LoopVar->setInvalidDecl();
@@ -2408,8 +2406,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
// Attach *__begin as initializer for VD. Don't touch it if we're just
// trying to determine whether this would be a valid range.
if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) {
- AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false,
- /*TypeMayContainAuto=*/true);
+ AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false);
if (LoopVar->isInvalidDecl())
NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 795e6025d96f..8ad5b5951ea3 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1224,9 +1224,17 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
}
+ // If this is a templated friend in a dependent context we should not put it
+ // on the redecl chain. In some cases, the templated friend can be the most
+ // recent declaration tricking the template instantiator to make substitutions
+ // there.
+ // FIXME: Figure out how to combine with shouldLinkDependentDeclWithPrevious
+ bool ShouldAddRedecl
+ = !(TUK == TUK_Friend && CurContext->isDependentContext());
+
CXXRecordDecl *NewClass =
CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
- PrevClassTemplate?
+ PrevClassTemplate && ShouldAddRedecl ?
PrevClassTemplate->getTemplatedDecl() : nullptr,
/*DelayTypeCreation=*/true);
SetNestedNameSpecifier(NewClass, SS);
@@ -1245,7 +1253,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
ClassTemplateDecl *NewTemplate
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
DeclarationName(Name), TemplateParams,
- NewClass, PrevClassTemplate);
+ NewClass);
+
+ if (ShouldAddRedecl)
+ NewTemplate->setPreviousDecl(PrevClassTemplate);
+
NewClass->setDescribedClassTemplate(NewTemplate);
if (ModulePrivateLoc.isValid())
@@ -1653,6 +1665,7 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
typedef RecursiveASTVisitor<DependencyChecker> super;
unsigned Depth;
+ bool FindLessThanDepth;
// Whether we're looking for a use of a template parameter that makes the
// overall construct type-dependent / a dependent type. This is strictly
@@ -1663,25 +1676,16 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
bool Match;
SourceLocation MatchLoc;
- DependencyChecker(unsigned Depth, bool IgnoreNonTypeDependent)
- : Depth(Depth), IgnoreNonTypeDependent(IgnoreNonTypeDependent),
- Match(false) {}
+ DependencyChecker(unsigned Depth, bool IgnoreNonTypeDependent,
+ bool FindLessThanDepth = false)
+ : Depth(Depth), FindLessThanDepth(FindLessThanDepth),
+ IgnoreNonTypeDependent(IgnoreNonTypeDependent), Match(false) {}
DependencyChecker(TemplateParameterList *Params, bool IgnoreNonTypeDependent)
- : IgnoreNonTypeDependent(IgnoreNonTypeDependent), Match(false) {
- NamedDecl *ND = Params->getParam(0);
- if (TemplateTypeParmDecl *PD = dyn_cast<TemplateTypeParmDecl>(ND)) {
- Depth = PD->getDepth();
- } else if (NonTypeTemplateParmDecl *PD =
- dyn_cast<NonTypeTemplateParmDecl>(ND)) {
- Depth = PD->getDepth();
- } else {
- Depth = cast<TemplateTemplateParmDecl>(ND)->getDepth();
- }
- }
+ : DependencyChecker(Params->getDepth(), IgnoreNonTypeDependent) {}
bool Matches(unsigned ParmDepth, SourceLocation Loc = SourceLocation()) {
- if (ParmDepth >= Depth) {
+ if (FindLessThanDepth ^ (ParmDepth >= Depth)) {
Match = true;
MatchLoc = Loc;
return true;
@@ -2336,15 +2340,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// A<T, T> have identical types when A is declared as:
//
// template<typename T, typename U = T> struct A;
- TemplateName CanonName = Context.getCanonicalTemplateName(Name);
- CanonType = Context.getTemplateSpecializationType(CanonName,
- Converted);
-
- // FIXME: CanonType is not actually the canonical type, and unfortunately
- // it is a TemplateSpecializationType that we will never use again.
- // In the future, we need to teach getTemplateSpecializationType to only
- // build the canonical type and return that to us.
- CanonType = Context.getCanonicalType(CanonType);
+ CanonType = Context.getCanonicalTemplateSpecializationType(Name, Converted);
// This might work out to be a current instantiation, in which
// case the canonical type needs to be the InjectedClassNameType.
@@ -3452,7 +3448,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
TemplateTypeParmDecl *Param,
- SmallVectorImpl<TemplateArgument> &Converted) {
+ SmallVectorImpl<TemplateArgument> &Converted) {
TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo();
// If the argument type is dependent, instantiate it now based
@@ -5838,6 +5834,15 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
return E;
}
+static bool isDependentOnOuter(NonTypeTemplateParmDecl *NTTP) {
+ if (NTTP->getDepth() == 0 || !NTTP->getType()->isDependentType())
+ return false;
+ DependencyChecker Checker(NTTP->getDepth(), /*IgnoreNonTypeDependent*/ false,
+ /*FindLessThanDepth*/ true);
+ Checker.TraverseType(NTTP->getType());
+ return Checker.Match;
+}
+
/// \brief Match two template parameters within template parameter lists.
static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
bool Complain,
@@ -5894,11 +5899,10 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
// If we are matching a template template argument to a template
// template parameter and one of the non-type template parameter types
- // is dependent, then we must wait until template instantiation time
- // to actually compare the arguments.
+ // is dependent on an outer template's parameter, then we must wait until
+ // template instantiation time to actually compare the arguments.
if (Kind == Sema::TPL_TemplateTemplateArgumentMatch &&
- (OldNTTP->getType()->isDependentType() ||
- NewNTTP->getType()->isDependentType()))
+ (isDependentOnOuter(OldNTTP) || isDependentOnOuter(NewNTTP)))
return true;
if (!S.Context.hasSameType(OldNTTP->getType(), NewNTTP->getType())) {
@@ -7785,6 +7789,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->setTemplateKeywordLoc(TemplateLoc);
Specialization->setBraceRange(SourceRange());
+ bool PreviouslyDLLExported = Specialization->hasAttr<DLLExportAttr>();
if (Attr)
ProcessDeclAttributeList(S, Specialization, Attr);
@@ -7847,8 +7852,9 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Fix a TSK_ImplicitInstantiation followed by a
// TSK_ExplicitInstantiationDefinition
- if (Old_TSK == TSK_ImplicitInstantiation &&
- Specialization->hasAttr<DLLExportAttr>() &&
+ bool NewlyDLLExported =
+ !PreviouslyDLLExported && Specialization->hasAttr<DLLExportAttr>();
+ if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported &&
(Context.getTargetInfo().getCXXABI().isMicrosoft() ||
Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
// In the MS ABI, an explicit instantiation definition can add a dll
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index ba4a5b7bc0d7..9f744a1dc1b2 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2264,9 +2264,6 @@ bool Sema::InstantiateInClassInitializer(
if (auto *L = getASTMutationListener())
L->DefaultMemberInitializerInstantiated(Instantiation);
- // Exit the scope of this instantiation.
- SavedContext.pop();
-
// Return true if the in-class initializer is still missing.
return !Instantiation->getInClassInitializer();
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d2a5e5cb5312..48d8b94af153 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1219,8 +1219,10 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
ClassTemplateDecl *Inst
= ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(),
- D->getIdentifier(), InstParams, RecordInst,
- PrevClassTemplate);
+ D->getIdentifier(), InstParams, RecordInst);
+ assert(!(isFriend && Owner->isDependentContext()));
+ Inst->setPreviousDecl(PrevClassTemplate);
+
RecordInst->setDescribedClassTemplate(Inst);
if (isFriend) {
@@ -4085,7 +4087,6 @@ void Sema::InstantiateVariableInitializer(
}
if (!Init.isInvalid()) {
- bool TypeMayContainAuto = true;
Expr *InitExpr = Init.get();
if (Var->hasAttr<DLLImportAttr>() &&
@@ -4094,9 +4095,9 @@ void Sema::InstantiateVariableInitializer(
// Do not dynamically initialize dllimport variables.
} else if (InitExpr) {
bool DirectInit = OldVar->isDirectInit();
- AddInitializerToDecl(Var, InitExpr, DirectInit, TypeMayContainAuto);
+ AddInitializerToDecl(Var, InitExpr, DirectInit);
} else
- ActOnUninitializedDecl(Var, TypeMayContainAuto);
+ ActOnUninitializedDecl(Var);
} else {
// FIXME: Not too happy about invalidating the declaration
// because of a bogus initializer.
@@ -4119,7 +4120,7 @@ void Sema::InstantiateVariableInitializer(
if (Var->isCXXForRangeDecl())
return;
- ActOnUninitializedDecl(Var, false);
+ ActOnUninitializedDecl(Var);
}
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index ae9a3ee790e1..29b21426790e 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -5263,7 +5263,7 @@ namespace {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
TL.setParam(tpi++, Param);
}
- // FIXME: exception specs
+ TL.setExceptionSpecRange(FTI.getExceptionSpecRange());
}
void VisitParenTypeLoc(ParenTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Paren);
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 66892936e573..c2aa3fef67c8 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -5023,6 +5023,7 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType(
NewTL.setLocalRangeBegin(TL.getLocalRangeBegin());
NewTL.setLParenLoc(TL.getLParenLoc());
NewTL.setRParenLoc(TL.getRParenLoc());
+ NewTL.setExceptionSpecRange(TL.getExceptionSpecRange());
NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
for (unsigned i = 0, e = NewTL.getNumParams(); i != e; ++i)
NewTL.setParam(i, ParamDecls[i]);
@@ -7779,6 +7780,18 @@ StmtResult TreeTransform<Derived>::
return Res;
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPTargetTeamsDistributeSimdDirective(
+ OMPTargetTeamsDistributeSimdDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(
+ OMPD_target_teams_distribute_simd, DirName, nullptr, D->getLocStart());
+ auto Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clause transformation