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);
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);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits