[PATCH] D65022: [Sema] Always instantiate the initializer of a variable template with undeduced type (8.0 regression)

2019-08-14 Thread Erik Pilkington via Phabricator via cfe-commits
erik.pilkington added a comment.

Hmm, looks like this patch fails to fix the case where we're referencing the 
variable in an non-odr use context, since we don't even bother to instantiate 
the initializer here:

  template 
  struct S {
template 
static constexpr auto x = 43;
  };
  
  int main() {
sizeof(S::x);
  }

I think we should instantiate the initializer before forming a referencing 
expression and marking it used. @rsmith: do you mind if I just land 
https://reviews.llvm.org/D65022?id=210905 and file a bug to fix the regression 
we're seeing here?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65022/new/

https://reviews.llvm.org/D65022



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65022: [Sema] Always instantiate the initializer of a variable template with undeduced type (8.0 regression)

2019-07-30 Thread Erik Pilkington via Phabricator via cfe-commits
erik.pilkington updated this revision to Diff 212470.
erik.pilkington added a comment.

Rebase on top of r367367.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65022/new/

https://reviews.llvm.org/D65022

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp


Index: clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
===
--- clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -424,3 +424,34 @@
 }
 }
 #endif
+
+#ifndef PRECXX11
+namespace auto_variable_instantiate_initializer {
+template  struct S {
+  template  static constexpr auto v = 1;
+  template  static constexpr auto v2 = T{};
+
+  template >
+  void implicit() {
+double d = v2;
+int i2 = v;
+  }
+
+  void implicit_nondep() {
+int i = v;
+double d = v2;
+  }
+};
+
+void useit() {
+  S x;
+  // We used to fail to instantiate the initializer, leading to an auto type
+  // leaking through here.
+  int i = x.v;
+  float j = x.v2;
+
+  x.implicit();
+  x.implicit_nondep();
+}
+}
+ #endif
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1160,11 +1160,17 @@
   }
   if (VarTemplateDecl *VarTempl = dyn_cast(MemberDecl)) {
 if (VarDecl *Var = getVarTemplateSpecialization(
-VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc))
-  return BuildMemberExpr(
+VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) {
+  MemberExpr *ME = BuildMemberExpr(
   BaseExpr, IsArrow, OpLoc, , TemplateKWLoc, Var, FoundDecl,
   /*HadMultipleCandidates=*/false, MemberNameInfo,
   Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
+
+  // BuildMemberExpr may have deduced an auto variable's type. Patch back
+  // that type to avoid forming an expression with undeduced type.
+  ME->setType(Var->getType().getNonReferenceType());
+  return ME;
+}
 return ExprError();
   }
 
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -3163,9 +3163,15 @@
   break;
 }
 
-return BuildDeclRefExpr(VD, type, valueKind, NameInfo, , FoundD,
-/*FIXME: TemplateKWLoc*/ SourceLocation(),
-TemplateArgs);
+DeclRefExpr *DRE = BuildDeclRefExpr(
+VD, type, valueKind, NameInfo, , FoundD,
+/*FIXME: TemplateKWLoc*/ SourceLocation(), TemplateArgs);
+
+// BuildDeclRefExpr may have deduced an auto variable's type. Patch back
+// that type to avoid forming an expression with undeduced type.
+if (isa(VD))
+  DRE->setType(VD->getType().getNonReferenceType());
+return DRE;
   }
 }
 


Index: clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
===
--- clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -424,3 +424,34 @@
 }
 }
 #endif
+
+#ifndef PRECXX11
+namespace auto_variable_instantiate_initializer {
+template  struct S {
+  template  static constexpr auto v = 1;
+  template  static constexpr auto v2 = T{};
+
+  template >
+  void implicit() {
+double d = v2;
+int i2 = v;
+  }
+
+  void implicit_nondep() {
+int i = v;
+double d = v2;
+  }
+};
+
+void useit() {
+  S x;
+  // We used to fail to instantiate the initializer, leading to an auto type
+  // leaking through here.
+  int i = x.v;
+  float j = x.v2;
+
+  x.implicit();
+  x.implicit_nondep();
+}
+}
+ #endif
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1160,11 +1160,17 @@
   }
   if (VarTemplateDecl *VarTempl = dyn_cast(MemberDecl)) {
 if (VarDecl *Var = getVarTemplateSpecialization(
-VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc))
-  return BuildMemberExpr(
+VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) {
+  MemberExpr *ME = BuildMemberExpr(
   BaseExpr, IsArrow, OpLoc, , TemplateKWLoc, Var, FoundDecl,
   /*HadMultipleCandidates=*/false, MemberNameInfo,
   Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
+
+  // BuildMemberExpr may have deduced an auto variable's type. Patch back
+  // that type to avoid forming an expression with undeduced type.
+  ME->setType(Var->getType().getNonReferenceType());
+  return ME;
+}
 return ExprError();
   }
 
Index: clang/lib/Sema/SemaExpr.cpp
===
--- 

[PATCH] D65022: [Sema] Always instantiate the initializer of a variable template with undeduced type (8.0 regression)

2019-07-26 Thread Erik Pilkington via Phabricator via cfe-commits
erik.pilkington updated this revision to Diff 212026.
erik.pilkington added a comment.

Fix the type of the MemberExpr/DeclRefExpr after instantiating the variable 
initializer.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65022/new/

https://reviews.llvm.org/D65022

Files:
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp


Index: clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
===
--- clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -395,3 +395,34 @@
   }
   int  = B::template n; // expected-error {{use of variable template 'n' 
requires template arguments}}
 }
+
+#ifndef PRECXX11
+namespace auto_variable_instantiate_initializer {
+template  struct S {
+  template  static constexpr auto v = 1;
+  template  static constexpr auto v2 = T{};
+
+  template >
+  void implicit() {
+double d = v2;
+int i2 = v;
+  }
+
+  void implicit_nondep() {
+int i = v;
+double d = v2;
+  }
+};
+
+void useit() {
+  S x;
+  // We used to fail to instantiate the initializer, leading to an auto type
+  // leaking through here.
+  int i = x.v;
+  float j = x.v2;
+
+  x.implicit();
+  x.implicit_nondep();
+}
+}
+#endif
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1160,11 +1160,17 @@
   }
   if (VarTemplateDecl *VarTempl = dyn_cast(MemberDecl)) {
 if (VarDecl *Var = getVarTemplateSpecialization(
-*this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc))
-  return BuildMemberExpr(
+*this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) {
+  MemberExpr *ME = BuildMemberExpr(
   BaseExpr, IsArrow, OpLoc, , TemplateKWLoc, Var, FoundDecl,
   /*HadMultipleCandidates=*/false, MemberNameInfo,
   Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
+
+  // BuildMemberExpr may have deduced an auto variable's type. Patch back
+  // that type to avoid forming an expression with undeduced type.
+  ME->setType(Var->getType().getNonReferenceType());
+  return ME;
+}
 return ExprError();
   }
 
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -3163,9 +3163,15 @@
   break;
 }
 
-return BuildDeclRefExpr(VD, type, valueKind, NameInfo, , FoundD,
-/*FIXME: TemplateKWLoc*/ SourceLocation(),
-TemplateArgs);
+DeclRefExpr *DRE = BuildDeclRefExpr(
+VD, type, valueKind, NameInfo, , FoundD,
+/*FIXME: TemplateKWLoc*/ SourceLocation(), TemplateArgs);
+
+// BuildDeclRefExpr may have deduced an auto variable's type. Patch back
+// that type to avoid forming an expression with undeduced type.
+if (isa(VD))
+  DRE->setType(VD->getType().getNonReferenceType());
+return DRE;
   }
 }
 


Index: clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
===
--- clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -395,3 +395,34 @@
   }
   int  = B::template n; // expected-error {{use of variable template 'n' requires template arguments}}
 }
+
+#ifndef PRECXX11
+namespace auto_variable_instantiate_initializer {
+template  struct S {
+  template  static constexpr auto v = 1;
+  template  static constexpr auto v2 = T{};
+
+  template >
+  void implicit() {
+double d = v2;
+int i2 = v;
+  }
+
+  void implicit_nondep() {
+int i = v;
+double d = v2;
+  }
+};
+
+void useit() {
+  S x;
+  // We used to fail to instantiate the initializer, leading to an auto type
+  // leaking through here.
+  int i = x.v;
+  float j = x.v2;
+
+  x.implicit();
+  x.implicit_nondep();
+}
+}
+#endif
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1160,11 +1160,17 @@
   }
   if (VarTemplateDecl *VarTempl = dyn_cast(MemberDecl)) {
 if (VarDecl *Var = getVarTemplateSpecialization(
-*this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc))
-  return BuildMemberExpr(
+*this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) {
+  MemberExpr *ME = BuildMemberExpr(
   BaseExpr, IsArrow, OpLoc, , TemplateKWLoc, Var, FoundDecl,
   /*HadMultipleCandidates=*/false, MemberNameInfo,
   Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
+
+  // BuildMemberExpr may have deduced an auto variable's type. Patch back
+  // that 

[PATCH] D65022: [Sema] Always instantiate the initializer of a variable template with undeduced type (8.0 regression)

2019-07-19 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added a comment.

Well, this restores an incorrect behaviour: we're not permitted to substitute 
into the initializer of the variable template here.

Can you look into fixing this properly, by instantiating the type when forming 
the MemberExpr? If not, taking this to fix the regression seems OK, but please 
file a bug for the introduced misbehaviour.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65022/new/

https://reviews.llvm.org/D65022



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65022: [Sema] Always instantiate the initializer of a variable template with undeduced type (8.0 regression)

2019-07-19 Thread Erik Pilkington via Phabricator via cfe-commits
erik.pilkington created this revision.
erik.pilkington added reviewers: rsmith, rjmccall.
Herald added subscribers: dexonsmith, jkorous.
Herald added a project: clang.

This patch fixes a regression introduced in r359947. Here:

  template  struct Outer {
template  static constexpr auto x = 1;
  };
  
  int main() {
Outer x;
int i = x.x;
  }

We'd defer the instantiation of the initializer of the variable template when 
instantiating Outer (leaving the variable template with an undeduced 
type). We do eventually instantiate the initializer and deduce the type of the 
variable when we're marking `Outer::x` referenced, but not before 
forming a MemberExpr that refers to the undeduced type. I think we could avoid 
instantiating the initializer of the variable template here, but that doesn't 
appear to be the intent of r359947, so this patch just falls back to the 8.0 
behaviour.

Fixes rdar://52619644

Thanks for taking a look!
Erik


Repository:
  rC Clang

https://reviews.llvm.org/D65022

Files:
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp


Index: clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
===
--- clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -395,3 +395,20 @@
   }
   int  = B::template n; // expected-error {{use of variable template 'n' 
requires template arguments}}
 }
+
+#ifndef PRECXX11
+namespace auto_variable_instantiate_initializer {
+template  struct S {
+  template  static constexpr auto v = 1;
+  template  static constexpr auto v2 = T{};
+};
+
+void useit() {
+  S x;
+  // We used to fail to instantiate the initializer, leading to an auto type
+  // leaking through here.
+  int i = x.v;
+  float j = x.v2;
+}
+}
+#endif
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4506,11 +4506,11 @@
   Context.setStaticLocalNumber(NewVar, Context.getStaticLocalNumber(OldVar));
 
   // Figure out whether to eagerly instantiate the initializer.
-  if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) {
-// We're producing a template. Don't instantiate the initializer yet.
-  } else if (NewVar->getType()->isUndeducedType()) {
+  if (NewVar->getType()->isUndeducedType()) {
 // We need the type to complete the declaration of the variable.
 InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
+  } else if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) {
+// We're producing a template. Don't instantiate the initializer yet.
   } else if (InstantiatingSpecFromTemplate ||
  (OldVar->isInline() && OldVar->isThisDeclarationADefinition() &&
   !NewVar->isThisDeclarationADefinition())) {


Index: clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
===
--- clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -395,3 +395,20 @@
   }
   int  = B::template n; // expected-error {{use of variable template 'n' requires template arguments}}
 }
+
+#ifndef PRECXX11
+namespace auto_variable_instantiate_initializer {
+template  struct S {
+  template  static constexpr auto v = 1;
+  template  static constexpr auto v2 = T{};
+};
+
+void useit() {
+  S x;
+  // We used to fail to instantiate the initializer, leading to an auto type
+  // leaking through here.
+  int i = x.v;
+  float j = x.v2;
+}
+}
+#endif
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4506,11 +4506,11 @@
   Context.setStaticLocalNumber(NewVar, Context.getStaticLocalNumber(OldVar));
 
   // Figure out whether to eagerly instantiate the initializer.
-  if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) {
-// We're producing a template. Don't instantiate the initializer yet.
-  } else if (NewVar->getType()->isUndeducedType()) {
+  if (NewVar->getType()->isUndeducedType()) {
 // We need the type to complete the declaration of the variable.
 InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
+  } else if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) {
+// We're producing a template. Don't instantiate the initializer yet.
   } else if (InstantiatingSpecFromTemplate ||
  (OldVar->isInline() && OldVar->isThisDeclarationADefinition() &&
   !NewVar->isThisDeclarationADefinition())) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org