r237647 - [modules] Support for merging a parsed definition of a static data member of a class template into an imported but hidden definition.
Richard Smith
richard-llvm at metafoo.co.uk
Mon May 18 17:49:29 PDT 2015
Author: rsmith
Date: Mon May 18 19:49:29 2015
New Revision: 237647
URL: http://llvm.org/viewvc/llvm-project?rev=237647&view=rev
Log:
[modules] Support for merging a parsed definition of a static data member of a class template into an imported but hidden definition.
Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=237647&r1=237646&r2=237647&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon May 18 19:49:29 2015
@@ -3404,14 +3404,23 @@ void Sema::MergeVarDecl(VarDecl *New, Lo
}
// C++ doesn't have tentative definitions, so go right ahead and check here.
- const VarDecl *Def;
+ VarDecl *Def;
if (getLangOpts().CPlusPlus &&
New->isThisDeclarationADefinition() == VarDecl::Definition &&
(Def = Old->getDefinition())) {
- Diag(New->getLocation(), diag::err_redefinition) << New;
- Diag(Def->getLocation(), diag::note_previous_definition);
- New->setInvalidDecl();
- return;
+ NamedDecl *Hidden = nullptr;
+ if (!hasVisibleDefinition(Def, &Hidden) &&
+ (New->getDescribedVarTemplate() ||
+ New->getNumTemplateParameterLists() ||
+ New->getDeclContext()->isDependentContext())) {
+ // The previous definition is hidden, and multiple definitions are
+ // permitted (in separate TUs). Form another definition of it.
+ } else {
+ Diag(New->getLocation(), diag::err_redefinition) << New;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ New->setInvalidDecl();
+ return;
+ }
}
if (haveIncompatibleLanguageLinkages(Old, New)) {
@@ -8883,16 +8892,24 @@ void Sema::AddInitializerToDecl(Decl *Re
VDecl->setInvalidDecl();
}
- const VarDecl *Def;
+ VarDecl *Def;
if ((Def = VDecl->getDefinition()) && Def != VDecl) {
- Diag(VDecl->getLocation(), diag::err_redefinition)
- << VDecl->getDeclName();
- Diag(Def->getLocation(), diag::note_previous_definition);
- VDecl->setInvalidDecl();
- return;
+ NamedDecl *Hidden = nullptr;
+ if (!hasVisibleDefinition(Def, &Hidden) &&
+ (VDecl->getDescribedVarTemplate() ||
+ VDecl->getNumTemplateParameterLists() ||
+ VDecl->getDeclContext()->isDependentContext())) {
+ // The previous definition is hidden, and multiple definitions are
+ // permitted (in separate TUs). Form another definition of it.
+ } else {
+ Diag(VDecl->getLocation(), diag::err_redefinition)
+ << VDecl->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ VDecl->setInvalidDecl();
+ return;
+ }
}
- const VarDecl *PrevInit = nullptr;
if (getLangOpts().CPlusPlus) {
// C++ [class.static.data]p4
// If a static data member is of const integral or const
@@ -8906,10 +8923,12 @@ void Sema::AddInitializerToDecl(Decl *Re
// We already performed a redefinition check above, but for static
// data members we also need to check whether there was an in-class
// declaration with an initializer.
- if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
+ if (VDecl->isStaticDataMember() && VDecl->getCanonicalDecl()->hasInit()) {
Diag(Init->getExprLoc(), diag::err_static_data_member_reinitialization)
<< VDecl->getDeclName();
- Diag(PrevInit->getInit()->getExprLoc(), diag::note_previous_initializer) << 0;
+ Diag(VDecl->getCanonicalDecl()->getInit()->getExprLoc(),
+ diag::note_previous_initializer)
+ << 0;
return;
}
Modified: cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h?rev=237647&r1=237646&r2=237647&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h (original)
+++ cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h Mon May 18 19:49:29 2015
@@ -26,9 +26,11 @@ template<typename T> int E(T t) { return
template<typename T> struct F {
int f();
template<typename U> int g();
+ static int n;
};
template<typename T> int F<T>::f() { return 0; }
template<typename T> template<typename U> int F<T>::g() { return 0; }
+template<typename T> int F<T>::n = 0;
template<> template<typename U> int F<char>::g() { return 0; }
template<> struct F<void> { int h(); };
inline int F<void>::h() { return 0; }
More information about the cfe-commits
mailing list