diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-05-19 00:49:29 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-05-19 00:49:29 +0000 |
| commit | 82e57fb1e8dad604f264994e6e9ac3c03d322b22 (patch) | |
| tree | 73fd41b3c46689b5db6b2bd588df572b50837dca | |
| parent | f3fa99c48e2a69b2df4a06249b987919b744acd9 (diff) | |
| download | bcm5719-llvm-82e57fb1e8dad604f264994e6e9ac3c03d322b22.tar.gz bcm5719-llvm-82e57fb1e8dad604f264994e6e9ac3c03d322b22.zip | |
[modules] Support for merging a parsed definition of a static data member of a class template into an imported but hidden definition.
llvm-svn: 237647
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 47 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/submodules-merge-defs/defs.h | 2 |
2 files changed, 35 insertions, 14 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 316700dc3d5..89f4b3a0c1f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3404,14 +3404,23 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { } // 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 *RealDecl, Expr *Init, 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 *RealDecl, Expr *Init, // 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; } diff --git a/clang/test/Modules/Inputs/submodules-merge-defs/defs.h b/clang/test/Modules/Inputs/submodules-merge-defs/defs.h index ffd996af184..f864d5762d2 100644 --- a/clang/test/Modules/Inputs/submodules-merge-defs/defs.h +++ b/clang/test/Modules/Inputs/submodules-merge-defs/defs.h @@ -26,9 +26,11 @@ template<typename T> int E(T t) { return t; } 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; } |

