[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