aaronpuchert updated this revision to Diff 258628.
aaronpuchert edited the summary of this revision.
aaronpuchert added a comment.

Slightly adapt test results: there is an additional error now.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76038

Files:
  clang/include/clang/AST/DeclBase.h
  clang/lib/AST/DeclBase.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaCXX/vartemplate-lambda.cpp
  clang/test/SemaTemplate/instantiate-local-class.cpp

Index: clang/test/SemaTemplate/instantiate-local-class.cpp
===================================================================
--- clang/test/SemaTemplate/instantiate-local-class.cpp
+++ clang/test/SemaTemplate/instantiate-local-class.cpp
@@ -486,3 +486,16 @@
   }
   void g() { f<int>(); }
 }
+
+namespace PR45000 {
+  template <typename T>
+  void f(int x = [](T x = nullptr) -> int { return x; }());
+  // expected-error@-1 {{cannot initialize a parameter of type 'int' with an rvalue of type 'nullptr_t'}}
+  // expected-note@-2 {{passing argument to parameter 'x' here}}
+  // expected-error@-3 {{no matching function for call}}
+  // expected-note@-4 {{candidate function not viable: requires single argument 'x', but no arguments were provided}}
+  // expected-note@-5 {{conversion candidate of type 'auto (*)(int) -> int'}}
+
+  void g() { f<int>(); }
+  // expected-note@-1 {{in instantiation of default function argument expression for 'f<int>' required here}}
+}
Index: clang/test/SemaCXX/vartemplate-lambda.cpp
===================================================================
--- clang/test/SemaCXX/vartemplate-lambda.cpp
+++ clang/test/SemaCXX/vartemplate-lambda.cpp
@@ -4,7 +4,12 @@
 template <typename> void foo0() { fn0<char>(); }
 
 template<typename T> auto fn1 = [](auto a) { return a + T(1); };
-template<typename T> auto v1 = [](int a = T(1)) { return a; }();
+template<typename T> auto v1 = [](int a = T()) { return a; }();
+// expected-error@-1{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}}
+// expected-error@-2{{no matching function for call}}
+// expected-note@-3{{passing argument to parameter 'a' here}}
+// expected-note@-4{{candidate function not viable}}
+// expected-note@-5{{conversion candidate of type 'int (*)(int)'}}
 
 struct S {
   template<class T>
@@ -16,6 +21,7 @@
   X a = 0x61;
   fn1<char>(a);
   (void)v1<int>;
+  (void)v1<int *>; // expected-note{{in instantiation of variable template specialization 'v1' requested here}}
   (void)S::t<int>; // expected-note{{in instantiation of static data member 'S::t<int>' requested here}}
   return 0;
 }
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -12159,19 +12159,6 @@
 
   LSI->CallOperator = NewCallOperator;
 
-  for (unsigned I = 0, NumParams = NewCallOperator->getNumParams();
-       I != NumParams; ++I) {
-    auto *P = NewCallOperator->getParamDecl(I);
-    if (P->hasUninstantiatedDefaultArg()) {
-      EnterExpressionEvaluationContext Eval(
-          getSema(),
-          Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed, P);
-      ExprResult R = getDerived().TransformExpr(
-          E->getCallOperator()->getParamDecl(I)->getDefaultArg());
-      P->setDefaultArg(R.get());
-    }
-  }
-
   getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
   getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
 
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4359,7 +4359,7 @@
         EPI.ExceptionSpec.Type != EST_None &&
         EPI.ExceptionSpec.Type != EST_DynamicNone &&
         EPI.ExceptionSpec.Type != EST_BasicNoexcept &&
-        !Tmpl->isLexicallyWithinFunctionOrMethod()) {
+        !Tmpl->isInLocalScope()) {
       FunctionDecl *ExceptionSpecTemplate = Tmpl;
       if (EPI.ExceptionSpec.Type == EST_Uninstantiated)
         ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate;
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2380,7 +2380,7 @@
     UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
   } else if (Expr *Arg = OldParm->getDefaultArg()) {
     FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext());
-    if (OwningFunc->isLexicallyWithinFunctionOrMethod()) {
+    if (OwningFunc->isInLocalScope()) {
       // Instantiate default arguments for methods of local classes (DR1484)
       // and non-defining declarations.
       Sema::ContextRAII SavedContext(*this, OwningFunc);
Index: clang/lib/AST/DeclBase.cpp
===================================================================
--- clang/lib/AST/DeclBase.cpp
+++ clang/lib/AST/DeclBase.cpp
@@ -332,13 +332,16 @@
   }
 }
 
-bool Decl::isLexicallyWithinFunctionOrMethod() const {
+bool Decl::isInLocalScope() const {
   const DeclContext *LDC = getLexicalDeclContext();
   while (true) {
     if (LDC->isFunctionOrMethod())
       return true;
     if (!isa<TagDecl>(LDC))
       return false;
+    if (const auto *CRD = dyn_cast<CXXRecordDecl>(LDC))
+      if (CRD->isLambda())
+        return true;
     LDC = LDC->getLexicalParent();
   }
   return false;
Index: clang/include/clang/AST/DeclBase.h
===================================================================
--- clang/include/clang/AST/DeclBase.h
+++ clang/include/clang/AST/DeclBase.h
@@ -869,14 +869,15 @@
     return getParentFunctionOrMethod() == nullptr;
   }
 
-  /// Returns true if this declaration lexically is inside a function.
-  /// It recognizes non-defining declarations as well as members of local
-  /// classes:
+  /// Returns true if this declaration is lexically inside a function or inside
+  /// a variable initializer. It recognizes non-defining declarations as well
+  /// as members of local classes:
   /// \code
   ///     void foo() { void bar(); }
   ///     void foo2() { class ABC { void bar(); }; }
+  ///     inline int x = [](){ return 0; };
   /// \endcode
-  bool isLexicallyWithinFunctionOrMethod() const;
+  bool isInLocalScope() const;
 
   /// If this decl is defined inside a function/method/block it returns
   /// the corresponding DeclContext, otherwise it returns null.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to