diff options
author | Erik Pilkington <erik.pilkington@gmail.com> | 2018-10-10 17:17:51 +0000 |
---|---|---|
committer | Erik Pilkington <erik.pilkington@gmail.com> | 2018-10-10 17:17:51 +0000 |
commit | d1a184fc6a4a121e8e17415573eaa29e1395cf8f (patch) | |
tree | 416e62b21dc4a7e93c6bddcc2b96046edbf121db /clang/lib/Sema/SemaDecl.cpp | |
parent | 8a39827eb3fd0b17cd5e820eb2d31d75597182df (diff) | |
download | bcm5719-llvm-d1a184fc6a4a121e8e17415573eaa29e1395cf8f.tar.gz bcm5719-llvm-d1a184fc6a4a121e8e17415573eaa29e1395cf8f.zip |
[Sema] Fix a multiple definition bug with friends and templates
The problem was that MergeFunctionDecl sometimes needs the injected template
arguments of a FunctionTemplateDecl, but is called before adding the new
template to the redecl chain. This leads to multiple common pointers in the same
redecl chain, each with their own identical instantiation. Fix this by merging
the the common state before inserting the new template into the redecl chain.
rdar://44810129
Differential revision: https://reviews.llvm.org/D53046
llvm-svn: 344157
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 441c54dc358..7ef1ad2bbb0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10022,11 +10022,17 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (FunctionTemplateDecl *OldTemplateDecl = dyn_cast<FunctionTemplateDecl>(OldDecl)) { auto *OldFD = OldTemplateDecl->getTemplatedDecl(); - NewFD->setPreviousDeclaration(OldFD); - adjustDeclContextForDeclaratorDecl(NewFD, OldFD); FunctionTemplateDecl *NewTemplateDecl = NewFD->getDescribedFunctionTemplate(); assert(NewTemplateDecl && "Template/non-template mismatch"); + + // The call to MergeFunctionDecl above may have created some state in + // NewTemplateDecl that needs to be merged with OldTemplateDecl before we + // can add it as a redeclaration. + NewTemplateDecl->mergePrevDecl(OldTemplateDecl); + + NewFD->setPreviousDeclaration(OldFD); + adjustDeclContextForDeclaratorDecl(NewFD, OldFD); if (NewFD->isCXXClassMember()) { NewFD->setAccess(OldTemplateDecl->getAccess()); NewTemplateDecl->setAccess(OldTemplateDecl->getAccess()); |