[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 <sepavloff () gmail ! com>
Date:       2015-08-03 19:15:19
Message-ID: f0342202d88c7fc791867876a9b12a07 () localhost ! localdomain
[Download RAW message or body]

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

Added method isLexicallyWithinFunctionOrMethod to class Decl.

Sorry, missed it from previous commit.


http://reviews.llvm.org/D11194

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


["D11194.31251.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
@@ -3250,6 +3250,9 @@
     if (CXXRecordDecl *Cls = dyn_cast<CXXRecordDecl>(Tmpl->getDeclContext())) {
       if (Cls->isLocalClass())
         RequireInstantiation = true;
+    } else if (Tmpl->isLexicallyWithinFunctionOrMethod()) {
+      // This is a non-defining declaration of a file scope function.
+      RequireInstantiation = true;
     }
     if (SemaRef.getLangOpts().CPlusPlus11 &&
         EPI.ExceptionSpec.Type != EST_None &&
Index: lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiate.cpp
+++ lib/Sema/SemaTemplateInstantiate.cpp
@@ -1691,6 +1691,16 @@
       ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
       if (NewArg.isUsable())
         NewParm->setDefaultArg(NewArg.get());
+    } else if (OwningFunc->isLexicallyWithinFunctionOrMethod()) {
+      // This is a function declaration within a function definition, as in:
+      //     template<class T> void f() {
+      //       void g(int x = T::v);
+      //     }
+      Sema::ContextRAII SavedContext(*this, OwningFunc);
+      LocalInstantiationScope Local(*this);
+      ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
+      if (NewArg.isUsable())
+        NewParm->setDefaultArg(NewArg.get());
     } else {
       // FIXME: if we non-lazily instantiated non-dependent default args for
       // non-dependent parameter types we could remove a bunch of duplicate
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -2716,7 +2716,7 @@
     // turn off ADL anyway).
     if (isa<UsingShadowDecl>(D))
       D = cast<UsingShadowDecl>(D)->getTargetDecl();
-    else if (D->getLexicalDeclContext()->isFunctionOrMethod())
+    else if (D->isLexicallyWithinFunctionOrMethod())
       return false;
 
     // C++0x [basic.lookup.argdep]p3:
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -1217,7 +1217,7 @@
   if (getLangOpts().CPlusPlus && D->isOutOfLine() &&
       !D->getDeclContext()->getRedeclContext()->Equals(
         D->getLexicalDeclContext()->getRedeclContext()) &&
-      !D->getLexicalDeclContext()->isFunctionOrMethod())
+      !D->isLexicallyWithinFunctionOrMethod())
     return;
 
   // Template instantiations should also not be pushed into scope.
@@ -3083,7 +3083,7 @@
       // local declaration will produce a hard error; if it doesn't
       // remain visible, a single bogus local redeclaration (which is
       // actually only a warning) could break all the downstream code.
-      if (!New->getLexicalDeclContext()->isFunctionOrMethod())
+      if (!New->isLexicallyWithinFunctionOrMethod())
         New->getIdentifier()->revertBuiltin();
 
       return false;
@@ -3277,12 +3277,12 @@
     //   scope in which the bound was specified, an omitted array bound
     //   is taken to be the same as in that earlier declaration.
     return NewVD->isPreviousDeclInSameBlockScope() ||
-           (!OldVD->getLexicalDeclContext()->isFunctionOrMethod() &&
-            !NewVD->getLexicalDeclContext()->isFunctionOrMethod());
+           (!OldVD->isLexicallyWithinFunctionOrMethod() &&
+            !NewVD->isLexicallyWithinFunctionOrMethod());
   } else {
     // If the old declaration was function-local, don't merge with its
     // type unless we're in the same function.
-    return !OldVD->getLexicalDeclContext()->isFunctionOrMethod() ||
+    return !OldVD->isLexicallyWithinFunctionOrMethod() ||
            OldVD->getLexicalDeclContext() == NewVD->getLexicalDeclContext();
   }
 }
@@ -10437,7 +10437,7 @@
        Prev; Prev = Prev->getPreviousDecl()) {
     // Ignore any declarations that occur in function or method
     // scope, because they aren't visible from the header.
-    if (Prev->getLexicalDeclContext()->isFunctionOrMethod())
+    if (Prev->isLexicallyWithinFunctionOrMethod())
       continue;
 
     MissingPrototype = !Prev->getType()->isFunctionProtoType();
Index: lib/AST/DeclBase.cpp
===================================================================
--- lib/AST/DeclBase.cpp
+++ lib/AST/DeclBase.cpp
@@ -266,6 +266,10 @@
   }
 }
 
+bool Decl::isLexicallyWithinFunctionOrMethod() const {
+  return getLexicalDeclContext()->isFunctionOrMethod();
+}
+
 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,13 @@
     return getParentFunctionOrMethod() == nullptr;
   }
 
+  /// \brief Returns true if this declaration lexically is inside a function.
+  /// In particular, it recognizes non-defining declarations such as:
+  /// \code
+  ///     void foo() { 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;



_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/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