@@ -89,7 +89,7 @@ Expr *CreateRefToDecl(Sema &S, ValueDecl *D, SourceLocation ExprLoc) {
8989 }
9090}
9191
92- static Decl *findInjectionCone (Decl *ContainingDecl) {
92+ Decl *findInjectionCone (Decl *ContainingDecl) {
9393 for (Decl *Ctx = ContainingDecl; Ctx;
9494 Ctx = cast<Decl>(Ctx->getDeclContext ())) {
9595 if (isa<RecordDecl, FunctionDecl, TranslationUnitDecl>(Ctx))
@@ -98,6 +98,56 @@ static Decl *findInjectionCone(Decl *ContainingDecl) {
9898 llvm_unreachable (" should have terminated at a TranslationUnitDecl" );
9999}
100100
101+ bool CheckReflectVar (Sema &S, VarDecl *VD, SourceRange Range) {
102+ // Reflections of 'init-capture's are always ill-formed.
103+ if (VD->isInitCapture ()) {
104+ S.Diag (Range.getBegin (), diag::err_reflect_init_capture) << Range;
105+ return true ;
106+ }
107+
108+ // All other cases that aren't local entities are fine.
109+ if (!VD->isLocalVarDeclOrParm () || VD->isStaticLocal ())
110+ return false ;
111+
112+ // Check for an intervening lambda scope.
113+ for (DeclContext *DC = S.CurContext ; DC != VD->getDeclContext ();
114+ DC = DC->getParent ()) {
115+ assert (DC && " Var context not a parent of the current context" );
116+ if (auto *RD = dyn_cast<CXXRecordDecl>(DC); RD && RD->isLambda ()) {
117+ S.Diag (Range.getBegin (), diag::err_reflect_intervening_lambda) << Range;
118+ return true ;
119+ }
120+ }
121+ return false ;
122+ }
123+
124+ bool CheckSpliceVar (Sema &S, VarDecl *VD, SourceRange Range) {
125+ // All non-local entities are fine.
126+ if (!VD->isLocalVarDeclOrParm () || VD->isStaticLocal ())
127+ return false ;
128+
129+ // Unevaluated contexts are fine.
130+ //
131+ // We should also ignore any enclosing 'typeid' expressions, but clang (as far
132+ // as I can tell) doesn't implement that for lambda captures either, so we
133+ // likewise ignore that here.
134+ if (!S.currentEvaluationContext ().isPotentiallyEvaluated ())
135+ return false ;
136+
137+ // Check for an intervening lambda scope.
138+ for (DeclContext *DC = S.CurContext ; DC != VD->getDeclContext ();
139+ DC = DC->getParent ()) {
140+ assert (DC && " Var context not a parent of the current context" );
141+ if (auto *RD = dyn_cast<CXXRecordDecl>(DC); RD && RD->isLambda ()) {
142+ S.Diag (Range.getBegin (), diag::err_splice_intervening_lambda)
143+ << VD << Range;
144+ S.Diag (VD->getLocation (), diag::note_entity_declared_at) << VD;
145+ return true ;
146+ }
147+ }
148+ return false ;
149+ }
150+
101151class MetaActionsImpl : public MetaActions {
102152 Sema &S;
103153
@@ -828,12 +878,8 @@ ExprResult Sema::ActOnCXXReflectExpr(SourceLocation OpLoc,
828878 return BuildCXXReflectExpr (OpLoc, NameInfo.getBeginLoc (), ND);
829879
830880 if (auto *VD = dyn_cast<VarDecl>(ND);
831- VD && (VD->isInitCapture ())) {
832- Diag (Id.StartLocation , diag::err_reflect_init_capture)
833- << Id.getSourceRange ();
881+ VD && CheckReflectVar (*this , VD, Id.getSourceRange ()))
834882 return ExprError ();
835- }
836-
837883
838884 // Why do we have to build an expression here? Just stash in an APValue?
839885 if (isa<VarDecl, BindingDecl, FunctionDecl, FieldDecl, EnumConstantDecl,
@@ -1527,6 +1573,10 @@ ExprResult Sema::BuildReflectionSpliceExpr(SourceLocation TemplateKWLoc,
15271573 return ExprError ();
15281574 }
15291575
1576+ if (auto *VD = dyn_cast<VarDecl>(TheDecl);
1577+ VD && CheckSpliceVar (*this , VD, Splice->getSourceRange ()))
1578+ return ExprError ();
1579+
15301580 // Create a new DeclRefExpr, since the operand of the reflect expression
15311581 // was parsed in an unevaluated context (but a splice expression is not
15321582 // necessarily, and frequently not, in such a context).
0 commit comments