[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cfe-commits
Subject:    Re: [PATCH] D11194: Instantiate function declarations in instantiated functions.
From:       Serge Pavlov via cfe-commits <cfe-commits () lists ! llvm ! org>
Date:       2015-08-17 15:40:37
Message-ID: b35e1945973230dbb5cf1d496749fbc2 () localhost ! localdomain
[Download RAW message or body]

sepavloff updated this revision to Diff 32310.
sepavloff added a comment.

Updated method isLexicallyWithinFunctionOrMethod according to Richard's not=
es.


http://reviews.llvm.org/D11194

Files:
  include/clang/AST/DeclBase.h
  lib/AST/DeclBase.cpp
  lib/Sema/SemaTemplateInstantiate.cpp
  lib/Sema/SemaTemplateInstantiateDecl.cpp
  test/SemaTemplate/default-arguments.cpp
  test/SemaTemplate/instantiate-exception-spec-cxx11.cpp


["D11194.32310.patch" (text/x-patch)]

Index: test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
===================================================================
--- test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
+++ test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
@@ -178,3 +178,11 @@
   }
 
 }
+
+namespace NondefDecls {
+  template<typename T> void f1() {
+    int g1(int) noexcept(T::error); // expected-error{{type 'int' cannot be used \
prior to '::' because it has no members}} +  }
+  template void f1<int>(); // expected-note{{in instantiation of function template \
specialization 'NondefDecls::f1<int>' requested here}} +}
+
Index: test/SemaTemplate/default-arguments.cpp
===================================================================
--- test/SemaTemplate/default-arguments.cpp
+++ test/SemaTemplate/default-arguments.cpp
@@ -159,3 +159,10 @@
 
   int g() { X<int>::f(0); } // expected-note {{in instantiation of template class \
'DR1635::X<int>' requested here}}  }
+
+namespace NondefDecls {
+  template<typename T> void f1() {
+    int g1(int defarg = T::error);  // expected-error{{type 'int' cannot be used \
prior to '::' because it has no members}} +  }
+  template void f1<int>();  // expected-note{{in instantiation of function template \
specialization 'NondefDecls::f1<int>' requested here}} +}
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3246,16 +3246,11 @@
     // exception specification.
     // DR1484: Local classes and their members are instantiated along with the
     // containing function.
-    bool RequireInstantiation = false;
-    if (CXXRecordDecl *Cls = dyn_cast<CXXRecordDecl>(Tmpl->getDeclContext())) {
-      if (Cls->isLocalClass())
-        RequireInstantiation = true;
-    }
     if (SemaRef.getLangOpts().CPlusPlus11 &&
         EPI.ExceptionSpec.Type != EST_None &&
         EPI.ExceptionSpec.Type != EST_DynamicNone &&
         EPI.ExceptionSpec.Type != EST_BasicNoexcept &&
-        !RequireInstantiation) {
+        !Tmpl->isLexicallyWithinFunctionOrMethod()) {
       FunctionDecl *ExceptionSpecTemplate = Tmpl;
       if (EPI.ExceptionSpec.Type == EST_Uninstantiated)
         ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate;
Index: lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiate.cpp
+++ lib/Sema/SemaTemplateInstantiate.cpp
@@ -1682,11 +1682,10 @@
     UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
   } else if (Expr *Arg = OldParm->getDefaultArg()) {
     FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext());
-    CXXRecordDecl *ClassD = dyn_cast<CXXRecordDecl>(OwningFunc->getDeclContext());
-    if (ClassD && ClassD->isLocalClass() && !ClassD->isLambda()) {
-      // If this is a method of a local class, as per DR1484 its default
-      // arguments must be instantiated.
-      Sema::ContextRAII SavedContext(*this, ClassD);
+    if (OwningFunc->isLexicallyWithinFunctionOrMethod()) {
+      // Instantiate default arguments for methods of local classes (DR1484)
+      // and non-defining declarations.
+      Sema::ContextRAII SavedContext(*this, OwningFunc);
       LocalInstantiationScope Local(*this);
       ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
       if (NewArg.isUsable())
Index: lib/AST/DeclBase.cpp
===================================================================
--- lib/AST/DeclBase.cpp
+++ lib/AST/DeclBase.cpp
@@ -266,6 +266,15 @@
   }
 }
 
+bool Decl::isLexicallyWithinFunctionOrMethod() const {
+  const DeclContext *LDC = getLexicalDeclContext();
+  if (LDC->isFunctionOrMethod())
+    return true;
+  if (const CXXRecordDecl *ClassD = dyn_cast<CXXRecordDecl>(LDC))
+    return ClassD->isLocalClass() && !ClassD->isLambda();;
+  return false;
+}
+
 bool Decl::isInAnonymousNamespace() const {
   const DeclContext *DC = getDeclContext();
   do {
Index: include/clang/AST/DeclBase.h
===================================================================
--- include/clang/AST/DeclBase.h
+++ include/clang/AST/DeclBase.h
@@ -728,6 +728,15 @@
     return getParentFunctionOrMethod() == nullptr;
   }
 
+  /// \brief Returns true if this declaration lexically is inside a function.
+  /// It recognizes non-defining declarations as well as members of local
+  /// classes:
+  /// \code
+  ///     void foo() { void bar(); }
+  ///     void foo2() { class ABC { void bar(); }; }
+  /// \endcode
+  bool isLexicallyWithinFunctionOrMethod() const;
+
   /// \brief If this decl is defined inside a function/method/block it returns
   /// the corresponding DeclContext, otherwise it returns null.
   const DeclContext *getParentFunctionOrMethod() const;


[Attachment #4 (text/plain)]

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


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic