@@ -14122,48 +14122,13 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
14122
14122
"Invalid Expr argument to DoMarkVarDeclReferenced");
14123
14123
Var->setReferenced();
14124
14124
14125
- TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
14126
- bool MarkODRUsed = true;
14127
-
14128
- // If the context is not potentially evaluated, this is not an odr-use and
14129
- // does not trigger instantiation.
14130
- if (!IsPotentiallyEvaluatedContext(SemaRef)) {
14131
- if (SemaRef.isUnevaluatedContext())
14132
- return;
14133
-
14134
- // If we don't yet know whether this context is going to end up being an
14135
- // evaluated context, and we're referencing a variable from an enclosing
14136
- // scope, add a potential capture.
14137
- //
14138
- // FIXME: Is this necessary? These contexts are only used for default
14139
- // arguments, where local variables can't be used.
14140
- const bool RefersToEnclosingScope =
14141
- (SemaRef.CurContext != Var->getDeclContext() &&
14142
- Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage());
14143
- if (RefersToEnclosingScope) {
14144
- if (LambdaScopeInfo *const LSI =
14145
- SemaRef.getCurLambda(/*IgnoreCapturedRegions=*/true)) {
14146
- // If a variable could potentially be odr-used, defer marking it so
14147
- // until we finish analyzing the full expression for any
14148
- // lvalue-to-rvalue
14149
- // or discarded value conversions that would obviate odr-use.
14150
- // Add it to the list of potential captures that will be analyzed
14151
- // later (ActOnFinishFullExpr) for eventual capture and odr-use marking
14152
- // unless the variable is a reference that was initialized by a constant
14153
- // expression (this will never need to be captured or odr-used).
14154
- assert(E && "Capture variable should be used in an expression.");
14155
- if (!Var->getType()->isReferenceType() ||
14156
- !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))
14157
- LSI->addPotentialCapture(E->IgnoreParens());
14158
- }
14159
- }
14160
-
14161
- if (!isTemplateInstantiation(TSK))
14162
- return;
14125
+ if (SemaRef.isUnevaluatedContext())
14126
+ return;
14163
14127
14164
- // Instantiate, but do not mark as odr-used, variable templates.
14165
- MarkODRUsed = false;
14166
- }
14128
+ TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
14129
+ bool MarkODRUsed = IsPotentiallyEvaluatedContext(SemaRef);
14130
+ bool NeedDefinition =
14131
+ MarkODRUsed || Var->isUsableInConstantExpressions(SemaRef.Context);
14167
14132
14168
14133
VarTemplateSpecializationDecl *VarSpec =
14169
14134
dyn_cast<VarTemplateSpecializationDecl>(Var);
@@ -14173,14 +14138,15 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
14173
14138
// If this might be a member specialization of a static data member, check
14174
14139
// the specialization is visible. We already did the checks for variable
14175
14140
// template specializations when we created them.
14176
- if (TSK != TSK_Undeclared && !isa<VarTemplateSpecializationDecl>(Var))
14141
+ if (NeedDefinition && TSK != TSK_Undeclared &&
14142
+ !isa<VarTemplateSpecializationDecl>(Var))
14177
14143
SemaRef.checkSpecializationVisibility(Loc, Var);
14178
14144
14179
14145
// Perform implicit instantiation of static data members, static data member
14180
14146
// templates of class templates, and variable template specializations. Delay
14181
14147
// instantiations of variable templates, except for those that could be used
14182
14148
// in a constant expression.
14183
- if (isTemplateInstantiation(TSK)) {
14149
+ if (NeedDefinition && isTemplateInstantiation(TSK)) {
14184
14150
bool TryInstantiating = TSK == TSK_ImplicitInstantiation;
14185
14151
14186
14152
if (TryInstantiating && !isa<VarTemplateSpecializationDecl>(Var)) {
@@ -14219,9 +14185,6 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
14219
14185
}
14220
14186
}
14221
14187
14222
- if (!MarkODRUsed)
14223
- return;
14224
-
14225
14188
// Per C++11 [basic.def.odr], a variable is odr-used "unless it satisfies
14226
14189
// the requirements for appearing in a constant expression (5.19) and, if
14227
14190
// it is an object, the lvalue-to-rvalue conversion (4.1)
@@ -14230,14 +14193,39 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
14230
14193
// Note that we use the C++11 definition everywhere because nothing in
14231
14194
// C++03 depends on whether we get the C++03 version correct. The second
14232
14195
// part does not apply to references, since they are not objects.
14233
- if (E && IsVariableAConstantExpression(Var, SemaRef.Context)) {
14196
+ if (MarkODRUsed && E && IsVariableAConstantExpression(Var, SemaRef.Context)) {
14234
14197
// A reference initialized by a constant expression can never be
14235
14198
// odr-used, so simply ignore it.
14236
14199
if (!Var->getType()->isReferenceType())
14237
14200
SemaRef.MaybeODRUseExprs.insert(E);
14238
- } else
14201
+ } else if (MarkODRUsed) {
14239
14202
MarkVarDeclODRUsed(Var, Loc, SemaRef,
14240
14203
/*MaxFunctionScopeIndex ptr*/ nullptr);
14204
+ } else {
14205
+ // If we don't yet know whether this context is going to end up being an
14206
+ // evaluated context, and we're referencing a variable from an enclosing
14207
+ // scope, add a potential capture.
14208
+ const bool RefersToEnclosingScope =
14209
+ (SemaRef.CurContext != Var->getDeclContext() &&
14210
+ Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage());
14211
+ if (RefersToEnclosingScope) {
14212
+ if (LambdaScopeInfo *const LSI =
14213
+ SemaRef.getCurLambda(/*IgnoreCapturedRegions=*/true)) {
14214
+ // If a variable could potentially be odr-used, defer marking it so
14215
+ // until we finish analyzing the full expression for any
14216
+ // lvalue-to-rvalue
14217
+ // or discarded value conversions that would obviate odr-use.
14218
+ // Add it to the list of potential captures that will be analyzed
14219
+ // later (ActOnFinishFullExpr) for eventual capture and odr-use marking
14220
+ // unless the variable is a reference that was initialized by a constant
14221
+ // expression (this will never need to be captured or odr-used).
14222
+ assert(E && "Capture variable should be used in an expression.");
14223
+ if (!Var->getType()->isReferenceType() ||
14224
+ !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))
14225
+ LSI->addPotentialCapture(E->IgnoreParens());
14226
+ }
14227
+ }
14228
+ }
14241
14229
}
14242
14230
14243
14231
/// \brief Mark a variable referenced, and check whether it is odr-used
@@ -14346,33 +14334,28 @@ namespace {
14346
14334
MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { }
14347
14335
14348
14336
bool TraverseTemplateArgument(const TemplateArgument &Arg);
14349
- bool TraverseRecordType(RecordType *T);
14350
14337
};
14351
14338
}
14352
14339
14353
14340
bool MarkReferencedDecls::TraverseTemplateArgument(
14354
14341
const TemplateArgument &Arg) {
14355
- if (Arg.getKind() == TemplateArgument::Declaration) {
14356
- if (Decl *D = Arg.getAsDecl())
14357
- S.MarkAnyDeclReferenced(Loc, D, true);
14342
+ {
14343
+ // A non-type template argument is a constant-evaluated context.
14344
+ EnterExpressionEvaluationContext Evaluated(S, Sema::ConstantEvaluated);
14345
+ if (Arg.getKind() == TemplateArgument::Declaration) {
14346
+ if (Decl *D = Arg.getAsDecl())
14347
+ S.MarkAnyDeclReferenced(Loc, D, true);
14348
+ } else if (Arg.getKind() == TemplateArgument::Expression) {
14349
+ S.MarkDeclarationsReferencedInExpr(Arg.getAsExpr(), false);
14350
+ }
14358
14351
}
14359
14352
14360
14353
return Inherited::TraverseTemplateArgument(Arg);
14361
14354
}
14362
14355
14363
- bool MarkReferencedDecls::TraverseRecordType(RecordType *T) {
14364
- if (ClassTemplateSpecializationDecl *Spec
14365
- = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) {
14366
- const TemplateArgumentList &Args = Spec->getTemplateArgs();
14367
- return TraverseTemplateArguments(Args.data(), Args.size());
14368
- }
14369
-
14370
- return true;
14371
- }
14372
-
14373
14356
void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {
14374
14357
MarkReferencedDecls Marker(*this, Loc);
14375
- Marker.TraverseType(Context.getCanonicalType(T) );
14358
+ Marker.TraverseType(T );
14376
14359
}
14377
14360
14378
14361
namespace {
0 commit comments