]> granicus.if.org Git - clang/commitdiff
[Sema] Fix handling of enumerators used as default arguments of lambda
authorAkira Hatanaka <ahatanaka@apple.com>
Fri, 16 Dec 2016 03:19:41 +0000 (03:19 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Fri, 16 Dec 2016 03:19:41 +0000 (03:19 +0000)
expressions in a function or class template.

This patch makes the following changes:

- Create a DependentScopeDeclRefExpr for the default argument instead of
  a CXXDependentScopeMemberExpr.
- Pass CombineWithOuterScope=true so that the outer scope in which the
  enum is declared is searched for the instantiation of the enum.

This is the first part of https://reviews.llvm.org/D23096. Fixes PR28795

rdar://problem/27535319

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@289914 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/SemaTemplate/default-expr-arguments-3.cpp [new file with mode: 0644]

index 65ae962c3bf71a02308c3befad2e26a895e8e92b..9d4029a9124766aa0e53515085aed8ac40da1dc7 100644 (file)
@@ -429,7 +429,12 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
   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);
 
index 321fd6995be653a2b4c7fd7e45dfd88505709865..4e3862a14d65bed44c2bfbd59db7ba163e917c34 100644 (file)
@@ -1687,7 +1687,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
       // 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.
diff --git a/test/SemaTemplate/default-expr-arguments-3.cpp b/test/SemaTemplate/default-expr-arguments-3.cpp
new file mode 100644 (file)
index 0000000..94e3972
--- /dev/null
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -std=c++14 -emit-llvm -disable-llvm-optzns -verify %s
+// expected-no-diagnostics
+
+namespace PR28795 {
+  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:
+template <class T> struct class2 {
+  void bar() {
+    enum class foo { a, b };
+    [](foo f = foo::a) { return f; }();
+  }
+};
+
+template struct class2<int>;
+
+template<typename T>
+void f1() {
+  enum class foo { a, b };
+  struct S {
+    int g1(foo n = foo::a);
+  };
+}
+
+template void f1<int>();