This is an archive of the discontinued LLVM Phabricator instance.

Instantiate function declarations in instantiated functions.
ClosedPublic

Authored by sepavloff on Jul 14 2015, 12:52 PM.

Details

Summary

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.

Diff Detail

Repository
rL LLVM

Event Timeline

sepavloff updated this revision to Diff 29704.Jul 14 2015, 12:52 PM
sepavloff retitled this revision from to Instantiate function declarations in instantiated functions..
sepavloff updated this object.
sepavloff added a subscriber: cfe-commits.
rsmith added a subscriber: rsmith.Jul 14 2015, 1:51 PM

Please add a member to Decl, something like isLexicallyWithinFunctionOrMethod, and use it in both places rather than duplicating the local class / local function declaration check.

lib/Sema/SemaTemplateInstantiate.cpp
1695 ↗(On Diff #29704)

Is this necessary? A local function declaration can't be a definition.

sepavloff added inline comments.Jul 16 2015, 10:36 AM
lib/Sema/SemaTemplateInstantiate.cpp
1695 ↗(On Diff #29704)

As clang do not support nested functions, it is not necessary. Remove it.

sepavloff updated this revision to Diff 29921.Jul 16 2015, 10:37 AM

Address reviewer's comments.

Ping.

Thanks,
--Serge

I think maybe you missed my comment from before: "Please add a member to Decl, something like isLexicallyWithinFunctionOrMethod, and use it in both places rather than duplicating the local class / local function declaration check."

sepavloff updated this revision to Diff 31251.Aug 3 2015, 12:15 PM

Added method isLexicallyWithinFunctionOrMethod to class Decl.

Sorry, missed it from previous commit.

rsmith added inline comments.Aug 3 2015, 12:23 PM
lib/AST/DeclBase.cpp
269–271 ↗(On Diff #31251)

This should also return true if the lexical decl context is a local class. The point is to allow you to remove the code duplication you added in the other changes in this patch.

sepavloff updated this revision to Diff 32310.Aug 17 2015, 8:40 AM

Updated method isLexicallyWithinFunctionOrMethod according to Richard's notes.

rsmith added inline comments.Aug 17 2015, 1:57 PM
lib/AST/DeclBase.cpp
273 ↗(On Diff #32310)

It's not necessary for this change, but to match its documentation this function should handle other kinds of TagDecl too (enums, C structs). Something like:

do {
  if (LDC->isFunctionOrMethod())
    return true;
  if (!isa<TagDecl>(LDC))
    return false;
  LDC = LDC->getLexicalParent();
} while (LDC);
return false;

... maybe?

274 ↗(On Diff #32310)

You have a double-semicolon here.

274 ↗(On Diff #32310)

Why are you discounting lambdas here?

sepavloff added inline comments.Aug 18 2015, 10:05 AM
lib/AST/DeclBase.cpp
273 ↗(On Diff #32310)

The proposed code recognizes lambda as lexically contained within a function. As a result, the following test starts to fail (obtained from CXX\expr\expr.prim\expr.prim.lambda\default-arguments.cpp):

struct NoDefaultCtor {
  NoDefaultCtor(const NoDefaultCtor&); // expected-note{{candidate constructor}}
  ~NoDefaultCtor();
};

template<typename T>
void defargs_in_template_unused(T t) {
  auto l1 = [](const T& value = T()) { };
  l1(t);
}

template void defargs_in_template_unused(NoDefaultCtor);

because default value for lambda argument cannot be instantiated. It is not clear whether instantiation of the lambda default argument must always occur similar to DR1484. I couldn't find appropriate place in the standard. According to spirit it shouldn't as lambda is not a separate declaration but a part of instantiated content. If so 14.6.4.1p2 is more likely to be applied and the above test must pass.

Maybe we need to rename isLexicallyWithinFunctionOrMethod to shouldBeAlwaysInstantiated or something like that to avoid misunderstanding?

sepavloff updated this revision to Diff 32597.Aug 19 2015, 12:49 PM

Lambda functions are now treated as local classes.

rsmith accepted this revision.Aug 20 2015, 2:21 PM
rsmith added a reviewer: rsmith.

LGTM with a couple of tweaks. Thanks!

lib/AST/DeclBase.cpp
276 ↗(On Diff #32597)

getLexicalParent()?

277–278 ↗(On Diff #32597)

I think we can actually recast this loop as while (true), since we must eventually reach the TU and return false.

This revision is now accepted and ready to land.Aug 20 2015, 2:21 PM
This revision was automatically updated to reflect the committed changes.