[PATCH] D23096: [Sema] Pass CombineWithOuterScope = true to constructor of LocalInstantiationScope

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 10 16:06:42 PDT 2016


ahatanak updated this revision to Diff 67623.
ahatanak added a comment.

Handle the case in which the enum is declared inside a member function and add test cases.

The variable template test case still crashes. It looks like it crashes whenever the lambda expression takes a default argument:

template <class T> auto a = [](int f = 7) { return f; }();

auto foo1() {

  return a<int>;

}


https://reviews.llvm.org/D23096

Files:
  lib/Sema/SemaTemplate.cpp
  lib/Sema/SemaTemplateInstantiate.cpp
  test/SemaTemplate/default-expr-arguments-3.cpp

Index: test/SemaTemplate/default-expr-arguments-3.cpp
===================================================================
--- /dev/null
+++ test/SemaTemplate/default-expr-arguments-3.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -std=c++14 -ast-dump %s 2>&1 | FileCheck %s
+
+namespace PR28795 {
+  // CHECK: FunctionDecl{{.*}}func 'void (void)'
+  // CHECK:  LambdaExpr
+  // CHECK:   CXXMethodDecl{{.*}}operator() 'enum foo (enum foo) const' inline
+  // CHECK:    ParmVarDecl{{.*}}f 'enum foo' cinit
+  // CHECK:     DeclRefExpr{{.*}}'enum foo' EnumConstant{{.*}}'a' 'enum foo'
+
+  template<typename T>
+  void func() {
+    enum class foo { a, b };
+    auto bar = [](foo f = foo::a) { return f; };
+    bar();
+  }
+
+  void foo() {
+    func<int>();
+  }
+}
+
+// Template struct case:
+
+// CHECK: ClassTemplateSpecializationDecl{{.*}}struct class2 definition
+// CHECK:  LambdaExpr
+// CHECK:   CXXMethodDecl{{.*}}used operator() 'enum foo (enum foo) const' inline
+// CHECK:    ParmVarDecl{{.*}}f 'enum foo' cinit
+// CHECK:     DeclRefExpr{{.*}}'enum foo' EnumConstant{{.*}}'a' 'enum foo'
+
+template <class T> struct class2 {
+  void bar() {
+    enum class foo { a, b };
+    [](foo f = foo::a) { return f; }();
+  }
+};
+
+template struct class2<int>;
+
+// CHECK: FunctionDecl{{.*}}f1 'void (void)'
+// CHECK:  CXXMethodDecl{{.*}}g1 'int (enum foo)'
+// CHECK:   ParmVarDecl{{.*}}n 'enum foo' cinit
+// CHECK:    DeclRefExpr{{.*}}'enum foo' EnumConstant{{.*}}'a' 'enum foo'
+
+template<typename T>
+void f1() {
+  enum class foo { a, b };
+  struct S {
+    int g1(foo n = foo::a);
+  };
+}
+
+template void f1<int>();
Index: lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiate.cpp
+++ lib/Sema/SemaTemplateInstantiate.cpp
@@ -1670,7 +1670,7 @@
       // Instantiate default arguments for methods of local classes (DR1484)
       // and non-defining declarations.
       Sema::ContextRAII SavedContext(*this, OwningFunc);
-      LocalInstantiationScope Local(*this);
+      LocalInstantiationScope Local(*this, true);
       ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
       if (NewArg.isUsable()) {
         // It would be nice if we still had this.
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -429,7 +429,12 @@
   bool MightBeCxx11UnevalField =
       getLangOpts().CPlusPlus11 && isUnevaluatedContext();
 
-  if (!MightBeCxx11UnevalField && !isAddressOfOperand &&
+  // Check if the nested name specifier is an enum type.
+  bool IsEnum = false;
+  if (NestedNameSpecifier *NNS = SS.getScopeRep())
+    IsEnum = dyn_cast_or_null<EnumType>(NNS->getAsType());
+
+  if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum &&
       isa<CXXMethodDecl>(DC) && cast<CXXMethodDecl>(DC)->isInstance()) {
     QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType(Context);
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D23096.67623.patch
Type: text/x-patch
Size: 3007 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160810/0965a9a7/attachment.bin>


More information about the cfe-commits mailing list