diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 95c83ebfaeab..1542a07713fb 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -20,6 +20,7 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/Stack.h" @@ -8707,23 +8708,59 @@ Decl *Sema::ActOnConceptDefinition(Scope *S, // Check for conflicting previous declaration. DeclarationNameInfo NameInfo(NewDecl->getDeclName(), NameLoc); LookupResult Previous(*this, NameInfo, LookupOrdinaryName, - ForVisibleRedeclaration); + forRedeclarationInCurContext()); LookupName(Previous, S); - FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage=*/false, /*AllowInlineNamespace*/false); - if (!Previous.empty()) { - auto *Old = Previous.getRepresentativeDecl(); - Diag(NameLoc, isa<ConceptDecl>(Old) ? diag::err_redefinition : - diag::err_redefinition_different_kind) << NewDecl->getDeclName(); - Diag(Old->getLocation(), diag::note_previous_definition); - } + bool AddToScope = true; + CheckConceptRedefinition(NewDecl, Previous, AddToScope); ActOnDocumentableDecl(NewDecl); - PushOnScopeChains(NewDecl, S); + if (AddToScope) + PushOnScopeChains(NewDecl, S); return NewDecl; } +void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl, + LookupResult &Previous, bool &AddToScope) { + AddToScope = true; + + if (Previous.empty()) + return; + + auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()); + if (!OldConcept) { + auto *Old = Previous.getRepresentativeDecl(); + Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind) + << NewDecl->getDeclName(); + notePreviousDefinition(Old, NewDecl->getLocation()); + AddToScope = false; + return; + } + // Check if we can merge with a concept declaration. + bool IsSame = Context.isSameEntity(NewDecl, OldConcept); + if (!IsSame) { + Diag(NewDecl->getLocation(), diag::err_redefinition_different_concept) + << NewDecl->getDeclName(); + notePreviousDefinition(OldConcept, NewDecl->getLocation()); + AddToScope = false; + return; + } + if (hasReachableDefinition(OldConcept)) { + Diag(NewDecl->getLocation(), diag::err_redefinition) + << NewDecl->getDeclName(); + notePreviousDefinition(OldConcept, NewDecl->getLocation()); + AddToScope = false; + return; + } + if (!Previous.isSingleResult()) { + // FIXME: we should produce an error in case of ambig and failed lookups. + // Other decls (e.g. namespaces) also have this shortcoming. + return; + } + Context.setPrimaryMergedDecl(NewDecl, OldConcept); +} + /// \brief Strips various properties off an implicit instantiation /// that has just been explicitly specialized. static void StripImplicitInstantiation(NamedDecl *D) { |
