summaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-11-25 19:07:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-11-25 19:07:40 +0000
commit17c7957f023f02fc2c88f51f8908c19b52609275 (patch)
treec654618ff2d38e26916b49614d89fe01f4a4818d /lib/Sema
parentc477790a57f44875b9de2043f2eb47dff2d20133 (diff)
Notes
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.cpp12
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp2
-rw-r--r--lib/Sema/SemaDecl.cpp3
-rw-r--r--lib/Sema/SemaExpr.cpp8
-rw-r--r--lib/Sema/SemaExprCXX.cpp20
-rw-r--r--lib/Sema/SemaLambda.cpp16
-rw-r--r--lib/Sema/SemaOpenMP.cpp21
-rw-r--r--lib/Sema/SemaTemplate.cpp13
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp37
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp35
10 files changed, 130 insertions, 37 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index a242ace9f64e..777747606304 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -1197,11 +1197,19 @@ BlockScopeInfo *Sema::getCurBlock() {
return CurBSI;
}
-LambdaScopeInfo *Sema::getCurLambda() {
+LambdaScopeInfo *Sema::getCurLambda(bool IgnoreCapturedRegions) {
if (FunctionScopes.empty())
return nullptr;
- auto CurLSI = dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
+ auto I = FunctionScopes.rbegin();
+ if (IgnoreCapturedRegions) {
+ auto E = FunctionScopes.rend();
+ while (I != E && isa<CapturedRegionScopeInfo>(*I))
+ ++I;
+ if (I == E)
+ return nullptr;
+ }
+ auto *CurLSI = dyn_cast<LambdaScopeInfo>(*I);
if (CurLSI && CurLSI->Lambda &&
!CurLSI->Lambda->Encloses(CurContext)) {
// We have switched contexts due to template instantiation.
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index ab0e709a97e7..949263d24897 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -806,7 +806,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
if (!Found.empty()) {
if (TypeDecl *TD = Found.getAsSingle<TypeDecl>())
Diag(IdentifierLoc, diag::err_expected_class_or_namespace)
- << QualType(TD->getTypeForDecl(), 0) << getLangOpts().CPlusPlus;
+ << Context.getTypeDeclType(TD) << getLangOpts().CPlusPlus;
else {
Diag(IdentifierLoc, diag::err_expected_class_or_namespace)
<< &Identifier << getLangOpts().CPlusPlus;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index ea276a995d81..41719d4e7b08 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -9615,7 +9615,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
}
VarDecl *Def;
- if ((Def = VDecl->getDefinition()) && Def != VDecl) {
+ if ((Def = VDecl->getDefinition()) && Def != VDecl &&
+ (!VDecl->isStaticDataMember() || VDecl->isOutOfLine())) {
NamedDecl *Hidden = nullptr;
if (!hasVisibleDefinition(Def, &Hidden) &&
(VDecl->getFormalLinkage() == InternalLinkage ||
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index adcc38cbc4fd..719e1e3502ca 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4522,6 +4522,11 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
MutiLevelArgList.getInnermost());
if (Inst.isInvalid())
return ExprError();
+ if (Inst.isAlreadyInstantiating()) {
+ Diag(Param->getLocStart(), diag::err_recursive_default_argument) << FD;
+ Param->setInvalidDecl();
+ return ExprError();
+ }
ExprResult Result;
{
@@ -13880,7 +13885,8 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
(SemaRef.CurContext != Var->getDeclContext() &&
Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage());
if (RefersToEnclosingScope) {
- if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {
+ if (LambdaScopeInfo *const LSI =
+ SemaRef.getCurLambda(/*IgnoreCapturedRegions=*/true)) {
// If a variable could potentially be odr-used, defer marking it so
// until we finish analyzing the full expression for any
// lvalue-to-rvalue
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index b7a968e09d4d..56f4019bfbb6 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -6582,10 +6582,16 @@ static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
Expr *const FE, LambdaScopeInfo *const CurrentLSI, Sema &S) {
- assert(!S.isUnevaluatedContext());
- assert(S.CurContext->isDependentContext());
- assert(CurrentLSI->CallOperator == S.CurContext &&
+ assert(!S.isUnevaluatedContext());
+ assert(S.CurContext->isDependentContext());
+#ifndef NDEBUG
+ DeclContext *DC = S.CurContext;
+ while (DC && isa<CapturedDecl>(DC))
+ DC = DC->getParent();
+ assert(
+ CurrentLSI->CallOperator == DC &&
"The current call operator must be synchronized with Sema's CurContext");
+#endif // NDEBUG
const bool IsFullExprInstantiationDependent = FE->isInstantiationDependent();
@@ -7051,7 +7057,8 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
// and then the full-expression +n + ({ 0; }); ends, but it's too late
// for us to see that we need to capture n after all.
- LambdaScopeInfo *const CurrentLSI = getCurLambda();
+ LambdaScopeInfo *const CurrentLSI =
+ getCurLambda(/*IgnoreCapturedRegions=*/true);
// FIXME: PR 17877 showed that getCurLambda() can return a valid pointer
// even if CurContext is not a lambda call operator. Refer to that Bug Report
// for an example of the code that might cause this asynchrony.
@@ -7066,7 +7073,10 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
// constructor/destructor.
// - Teach the handful of places that iterate over FunctionScopes to
// stop at the outermost enclosing lexical scope."
- const bool IsInLambdaDeclContext = isLambdaCallOperator(CurContext);
+ DeclContext *DC = CurContext;
+ while (DC && isa<CapturedDecl>(DC))
+ DC = DC->getParent();
+ const bool IsInLambdaDeclContext = isLambdaCallOperator(DC);
if (IsInLambdaDeclContext && CurrentLSI &&
CurrentLSI->hasPotentialCaptures() && !FullExpr.isInvalid())
CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(FE, CurrentLSI,
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 8a2bf929dfc0..0b3af262cd61 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -66,17 +66,20 @@ getStackIndexOfNearestEnclosingCaptureReadyLambda(
// Label failure to capture.
const Optional<unsigned> NoLambdaIsCaptureReady;
+ // Ignore all inner captured regions.
+ unsigned CurScopeIndex = FunctionScopes.size() - 1;
+ while (CurScopeIndex > 0 && isa<clang::sema::CapturedRegionScopeInfo>(
+ FunctionScopes[CurScopeIndex]))
+ --CurScopeIndex;
assert(
- isa<clang::sema::LambdaScopeInfo>(
- FunctionScopes[FunctionScopes.size() - 1]) &&
+ isa<clang::sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]) &&
"The function on the top of sema's function-info stack must be a lambda");
-
+
// If VarToCapture is null, we are attempting to capture 'this'.
const bool IsCapturingThis = !VarToCapture;
const bool IsCapturingVariable = !IsCapturingThis;
// Start with the current lambda at the top of the stack (highest index).
- unsigned CurScopeIndex = FunctionScopes.size() - 1;
DeclContext *EnclosingDC =
cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex])->CallOperator;
@@ -311,18 +314,21 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
bool IsInNonspecializedTemplate =
!ActiveTemplateInstantiations.empty() || CurContext->isDependentContext();
switch (Kind) {
- case Normal:
+ case Normal: {
// -- the bodies of non-exported nonspecialized template functions
// -- the bodies of inline functions
if ((IsInNonspecializedTemplate &&
!(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) ||
isInInlineFunction(CurContext)) {
ManglingContextDecl = nullptr;
+ while (auto *CD = dyn_cast<CapturedDecl>(DC))
+ DC = CD->getParent();
return &Context.getManglingNumberContext(DC);
}
ManglingContextDecl = nullptr;
return nullptr;
+ }
case StaticDataMember:
// -- the initializers of nonspecialized static members of template classes
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index 3c8554893b43..b7ac48583e1a 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -9133,7 +9133,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
// for all threads of the team.
if (!ASE && !OASE && VD) {
VarDecl *VDDef = VD->getDefinition();
- if (VD->getType()->isReferenceType() && VDDef) {
+ if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
DSARefChecker Check(DSAStack);
if (Check.Visit(VDDef->getInit())) {
Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange;
@@ -10680,6 +10680,25 @@ static bool CheckMapConflicts(
if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
break;
}
+ // Check if the extra components of the expressions in the enclosing
+ // data environment are redundant for the current base declaration.
+ // If they are, the maps completely overlap, which is legal.
+ for (; SI != SE; ++SI) {
+ QualType Type;
+ if (auto *ASE =
+ dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
+ Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
+ } else if (auto *OASE =
+ dyn_cast<OMPArraySectionExpr>(SI->getAssociatedExpression())) {
+ auto *E = OASE->getBase()->IgnoreParenImpCasts();
+ Type =
+ OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
+ }
+ if (Type.isNull() || Type->isAnyPointerType() ||
+ CheckArrayExpressionDoesNotReferToWholeSize(
+ SemaRef, SI->getAssociatedExpression(), Type))
+ break;
+ }
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
// List items of map clauses in the same construct must not share
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 7fc5db82d32c..72e499342f8f 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3256,7 +3256,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
// on the previously-computed template arguments.
if (ArgType->getType()->isDependentType()) {
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
- Template, Converted,
+ Param, Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return nullptr;
@@ -3308,7 +3308,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
NonTypeTemplateParmDecl *Param,
SmallVectorImpl<TemplateArgument> &Converted) {
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
- Template, Converted,
+ Param, Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return ExprError();
@@ -3359,8 +3359,9 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateTemplateParmDecl *Param,
SmallVectorImpl<TemplateArgument> &Converted,
NestedNameSpecifierLoc &QualifierLoc) {
- Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Template, Converted,
- SourceRange(TemplateLoc, RAngleLoc));
+ Sema::InstantiatingTemplate Inst(
+ SemaRef, TemplateLoc, TemplateParameter(Param), Template, Converted,
+ SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return TemplateName();
@@ -3981,7 +3982,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
}
// Introduce an instantiation record that describes where we are using
- // the default template argument.
+ // the default template argument. We're not actually instantiating a
+ // template here, we just create this object to put a note into the
+ // context stack.
InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 48c6a506ee36..65a5633bf0d5 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -225,6 +225,10 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Inst.NumTemplateArgs = TemplateArgs.size();
Inst.DeductionInfo = DeductionInfo;
Inst.InstantiationRange = InstantiationRange;
+ AlreadyInstantiating =
+ !SemaRef.InstantiatingSpecializations
+ .insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind))
+ .second;
SemaRef.InNonInstantiationSFINAEContext = false;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
if (!Inst.isInstantiationRecord())
@@ -247,13 +251,14 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
PointOfInstantiation, InstantiationRange, Entity) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
- Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template,
- ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
+ Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateParameter Param,
+ TemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef,
ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation,
- PointOfInstantiation, InstantiationRange, Template, nullptr,
- TemplateArgs) {}
+ PointOfInstantiation, InstantiationRange, getAsNamedDecl(Param),
+ Template, TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -263,7 +268,11 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
: InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation,
InstantiationRange, FunctionTemplate, nullptr,
- TemplateArgs, &DeductionInfo) {}
+ TemplateArgs, &DeductionInfo) {
+ assert(
+ Kind == ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution ||
+ Kind == ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
+}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -327,7 +336,8 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
void Sema::InstantiatingTemplate::Clear() {
if (!Invalid) {
- if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) {
+ auto &Active = SemaRef.ActiveTemplateInstantiations.back();
+ if (!Active.isInstantiationRecord()) {
assert(SemaRef.NonInstantiationEntries > 0);
--SemaRef.NonInstantiationEntries;
}
@@ -345,6 +355,10 @@ void Sema::InstantiatingTemplate::Clear() {
SemaRef.ActiveTemplateInstantiationLookupModules.pop_back();
}
+ if (!AlreadyInstantiating)
+ SemaRef.InstantiatingSpecializations.erase(
+ std::make_pair(Active.Entity, Active.Kind));
+
SemaRef.ActiveTemplateInstantiations.pop_back();
Invalid = true;
}
@@ -443,7 +457,7 @@ void Sema::PrintInstantiationStack() {
}
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
- TemplateDecl *Template = cast<TemplateDecl>(Active->Entity);
+ TemplateDecl *Template = cast<TemplateDecl>(Active->Template);
SmallVector<char, 128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
Template->printName(OS);
@@ -1950,6 +1964,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
+ assert(!Inst.isAlreadyInstantiating() && "should have been caught by caller");
PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
"instantiating class definition");
@@ -2175,6 +2190,8 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
+ if (Inst.isAlreadyInstantiating())
+ return false;
PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
"instantiating enum definition");
@@ -2249,6 +2266,12 @@ bool Sema::InstantiateInClassInitializer(
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
+ if (Inst.isAlreadyInstantiating()) {
+ // Error out if we hit an instantiation cycle for this initializer.
+ Diag(PointOfInstantiation, diag::err_in_class_initializer_cycle)
+ << Instantiation;
+ return true;
+ }
PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
"instantiating default member init");
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 6a213953ec9a..dd3748fb5337 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3360,6 +3360,13 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
UpdateExceptionSpec(Decl, EST_None);
return;
}
+ if (Inst.isAlreadyInstantiating()) {
+ // This exception specification indirectly depends on itself. Reject.
+ // FIXME: Corresponding rule in the standard?
+ Diag(PointOfInstantiation, diag::err_exception_spec_cycle) << Decl;
+ UpdateExceptionSpec(Decl, EST_None);
+ return;
+ }
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
@@ -3619,7 +3626,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
- if (Inst.isInvalid())
+ if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(),
"instantiating function definition");
@@ -3882,10 +3889,6 @@ void Sema::InstantiateVariableInitializer(
else if (OldVar->isInline())
Var->setImplicitlyInline();
- if (Var->getAnyInitializer())
- // We already have an initializer in the class.
- return;
-
if (OldVar->getInit()) {
if (Var->isStaticDataMember() && !OldVar->isOutOfLine())
PushExpressionEvaluationContext(Sema::ConstantEvaluated, OldVar);
@@ -3921,9 +3924,23 @@ void Sema::InstantiateVariableInitializer(
}
PopExpressionEvaluationContext();
- } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) &&
- !Var->isCXXForRangeDecl())
+ } else {
+ if (Var->isStaticDataMember()) {
+ if (!Var->isOutOfLine())
+ return;
+
+ // If the declaration inside the class had an initializer, don't add
+ // another one to the out-of-line definition.
+ if (OldVar->getFirstDecl()->hasInit())
+ return;
+ }
+
+ // We'll add an initializer to a for-range declaration later.
+ if (Var->isCXXForRangeDecl())
+ return;
+
ActOnUninitializedDecl(Var, false);
+ }
}
/// \brief Instantiate the definition of the given variable from its
@@ -4013,7 +4030,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// FIXME: Factor out the duplicated instantiation context setup/tear down
// code here.
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
- if (Inst.isInvalid())
+ if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
"instantiating variable initializer");
@@ -4142,7 +4159,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
- if (Inst.isInvalid())
+ if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
"instantiating variable definition");