Details
- Reviewers
rsmith
Diff Detail
Event Timeline
I expect this patch to cause problems if the two definitions of the variable template come from different modules, because at deserialization time we don't merge the definitions together sensibly (it looks like we end up with a redeclaration chain with multiple declarations, multiple of which believe they are "the" defintiion).
lib/Sema/SemaTemplate.cpp | ||
---|---|---|
470 | || on the previous line, please. | |
472–476 | Variable names should start with a capital letter. | |
478 | We'll need to extend hasVisibleDefinition to handle merged VarDecls to support this. (The ASTReader doesn't currently merge together VarDecl definitions in a reasonable way.) | |
512–513 | else if doesn't make sense here -- we either need to produce a diagnostic on all paths through here, or suppress the notes if we didn't produce a diagnostic. | |
530 | Likewise here. |
Address comments.
I still find the regression test a bit clumsy. I will try to add it to test/Modules/submodules-merge-defs.cpp, would this be the right place for it?
I think you'll also need to update the ASTDeclReader to merge VarDecl definitions together if it reads a definition and there already is one in the AST. I note that right now Sema::AddInitializerToDecl permits multiple definitions of a VarDecl, which doesn't seem like what we want here; we'll probably want to merge those as we parse them, too.
Now, we have a problem here: unlike with classes and functions, we can't always convert a variable definition to a declaration by just dropping the initializer. Perhaps we can add a flag to VarDecl to indicate "this is just a declaration, even though it looks like a definition", to handle that case? (This would also be useful for VarTemplateSpecializationDecls, where we currently reject valid code such as "template<typename> int n; int k = n<int>;" because we have no way to represent the difference between a mere declaration and a definition of n<int>.)
lib/Sema/SemaTemplate.cpp | ||
---|---|---|
505 | Why do we not issue a diagnostic in this case for a VarDecl when Complain is true and no definition is available? It seems like we should either be diagnosing this or asserting that it can't happen. | |
530 | else + assert would make more sense here. No other kind of declaration should get here. | |
lib/Sema/SemaType.cpp | ||
6904–6905 | We should add a getTemplateInstantiationPattern() to VarDecl and use it from here. |
This looks like it's going in the right direction.
lib/AST/Decl.cpp | ||
---|---|---|
2269–2272 | I think we need a similar check in the static data member case above. | |
2278 | enum? | |
lib/Sema/SemaTemplate.cpp | ||
512–513 | This function still appears to be able to return true (indicating to the caller that a diagnostic was produced) without actually producing a diagnostic. | |
lib/Serialization/ASTWriterDecl.cpp | ||
896–897 | Sink this flag into the "not for ParmVarDecl" block below. | |
1962 | Hmm. The width of the InitStyle field is definitely wrong right now, but should be fixed separately from this change. It looks like we don't hit this today because we don't use this abbreviation for a variable with an initializer. In addition to fixing the width of this field, we should also remove the getInit() == nullptr check when selecting the abbreviation in ASTDeclWriter::VisitVarDecl. |
lib/Sema/SemaTemplate.cpp | ||
---|---|---|
505 | I believe it is not implemented, i.e. we didn't have this diagnostics when VarDecl::getInstantiatedFromStaticDataMember is true. I added a FIXME: for a future enhancement. | |
512–513 | Is it better now? | |
lib/Serialization/ASTWriterDecl.cpp | ||
896–897 | I thought we might need this for c-style void f(struct S arg)-like constructs where we might need to demote if we merge ParmVarDecls. | |
1962 | Committed in r283444. |
lib/Sema/SemaDecl.cpp | ||
---|---|---|
3692–3693 | We always get here after calling that, don't we? So we only briefly have two definitions, between the point at which we attach the definition and now. If that's what you're referring to here, this comment could be clearer about it. | |
3695 | You should also call makeMergedDefinitionVisible(Def, New->getLocation()) here (and also call it for Def's enclosing template if this is a variable template definition) to make the prior definition visible. | |
lib/Serialization/ASTReaderDecl.cpp | ||
3083–3087 | I don't think this is worthwhile, since it's the first thing the loop below will check. | |
3089 | You should start at PrevVD not at D->First. This loop will currently only iterate once. | |
3090 | You can also bail out early and demote the current definition if you reach a previous demoted definition. That would reduce this from quadratic-time to linear-time. | |
lib/Serialization/ASTWriterDecl.cpp | ||
896–897 | We'll still have only one ParmVarDecl per FunctionDecl, and no-one cares whether a ParmVarDecl is a definition. Also, you assert that the flag is always false in this case below. |
Landed in r283882.
include/clang/AST/Decl.h | ||
---|---|---|
1222 | Ok. This would allow calling the method on already demoted definition. Do we want to allow that? | |
lib/AST/Decl.cpp | ||
2284 | Isn't that covered by the cases above? It seems there is no API to make such check, here. The current state looks to me consistent with CXXRecordDecl::getTemplateInstantiationPattern and FunctionDecl::getTemplateInstantiationPattern. | |
lib/Serialization/ASTReaderDecl.cpp | ||
3086–3090 | Good point ;) |
We should not access the IsThisDeclarationADemotedDefinition bits if the decl is ParmVarDecl.
I reverted this in r284081, and relanded with fixes described here as r284284.
lib/Sema/SemaDecl.cpp | ||
---|---|---|
9712 | We also need to do this work when MergeVarDecls encounters the same condition. | |
lib/Serialization/ASTReaderDecl.cpp | ||
3087 | When we do this, we need to tell the ASTContext we merged the definitions, so that the old definition will be made visible whenever the new one is. |
This is the bug. You can't read this bit here without first checking whether you are a ParmVarDecl, because ParmVarDecls don't have this bit at all.