summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerge Pavlov <sepavloff@gmail.com>2015-08-23 10:22:28 +0000
committerSerge Pavlov <sepavloff@gmail.com>2015-08-23 10:22:28 +0000
commit73c6a2448f24d13e16f34d46095ef7ad4bd1f145 (patch)
treefc6716a8bd34d19bb692312d00e1288344ff8f4b
parent1ac884d73afdc0c52c82e753cc45ae4887e753f7 (diff)
downloadbcm5719-llvm-73c6a2448f24d13e16f34d46095ef7ad4bd1f145.tar.gz
bcm5719-llvm-73c6a2448f24d13e16f34d46095ef7ad4bd1f145.zip
Instantiate function declarations in instantiated functions.
If a function declaration is found inside a template function as in: template<class T> void f() { void g(int x = T::v) except(T::w); } it must be instantiated along with the enclosing template function, including default arguments and exception specification. Together with the patch committed in r240974 this implements DR1484. Differential Revision: http://reviews.llvm.org/D11194 llvm-svn: 245810
-rw-r--r--clang/include/clang/AST/DeclBase.h9
-rw-r--r--clang/lib/AST/DeclBase.cpp12
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp9
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp7
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp13
-rw-r--r--clang/test/SemaTemplate/default-arguments.cpp7
-rw-r--r--clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp8
7 files changed, 49 insertions, 16 deletions
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 43d8366f0d5..f563a04d06d 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -728,6 +728,15 @@ public:
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;
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 40b135f9202..00d7d323b72 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -266,6 +266,18 @@ void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
}
}
+bool Decl::isLexicallyWithinFunctionOrMethod() const {
+ const DeclContext *LDC = getLexicalDeclContext();
+ do {
+ if (LDC->isFunctionOrMethod())
+ return true;
+ if (!isa<TagDecl>(LDC))
+ return false;
+ LDC = LDC->getParent();
+ } while (LDC);
+ return false;
+}
+
bool Decl::isInAnonymousNamespace() const {
const DeclContext *DC = getDeclContext();
do {
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 12cbd5bd4f1..031a2bad5f5 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1682,11 +1682,10 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
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())
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c8a067658bf..9899f1e8b1a 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3247,16 +3247,11 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
// 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;
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
index 38d5d0a6cd6..9b0a9ad8c25 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
@@ -26,23 +26,26 @@ struct NonPOD {
};
struct NoDefaultCtor {
- NoDefaultCtor(const NoDefaultCtor&); // expected-note{{candidate constructor}}
+ NoDefaultCtor(const NoDefaultCtor&); // expected-note{{candidate constructor}} \
+ // expected-note{{candidate constructor not viable: requires 1 argument, but 0 were provided}}
~NoDefaultCtor();
};
template<typename T>
void defargs_in_template_unused(T t) {
- auto l1 = [](const T& value = T()) { };
+ auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}}
l1(t);
}
template void defargs_in_template_unused(NonPOD);
-template void defargs_in_template_unused(NoDefaultCtor);
+template void defargs_in_template_unused(NoDefaultCtor); // expected-note{{in instantiation of function template specialization 'defargs_in_template_unused<NoDefaultCtor>' requested here}}
template<typename T>
void defargs_in_template_used() {
- auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}}
- l1(); // expected-note{{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}}
+ auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} \
+ // expected-note{{candidate function not viable: requires single argument 'value', but no arguments were provided}} \
+ // expected-note{{conversion candidate of type 'void (*)(const NoDefaultCtor &)'}}
+ l1(); // expected-error{{no matching function for call to object of type '(lambda at }}
}
template void defargs_in_template_used<NonPOD>();
diff --git a/clang/test/SemaTemplate/default-arguments.cpp b/clang/test/SemaTemplate/default-arguments.cpp
index 439a3039211..0e972522d40 100644
--- a/clang/test/SemaTemplate/default-arguments.cpp
+++ b/clang/test/SemaTemplate/default-arguments.cpp
@@ -159,3 +159,10 @@ namespace DR1635 {
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}}
+}
diff --git a/clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp b/clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
index f62ef61758a..6e8323d1ee2 100644
--- a/clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
+++ b/clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
@@ -178,3 +178,11 @@ namespace Variadic {
}
}
+
+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}}
+}
+
OpenPOWER on IntegriCloud