ChuanqiXu updated this revision to Diff 442791.
ChuanqiXu added a comment.
Rebase
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D128974/new/
https://reviews.llvm.org/D128974
Files:
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/DeclTemplate.h
clang/lib/AST/ASTContext.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/test/Modules/InheritDefaultArguments.cppm
clang/test/Modules/Inputs/PR31469/textual.h
Index: clang/test/Modules/Inputs/PR31469/textual.h
===================================================================
--- clang/test/Modules/Inputs/PR31469/textual.h
+++ clang/test/Modules/Inputs/PR31469/textual.h
@@ -4,7 +4,7 @@
template <class _Tp> class allocator;
template <class _Tp, class _Alloc = allocator<_Tp>> class list;
template <class _VoidPtr> class __list_iterator {
- //template <class> friend class list; // causes another crash in ASTDeclReader::attachPreviousDecl
+ template <class> friend class list;
template <class, class> friend class list;
};
template <class _Tp, class _Alloc> class __list_imp {};
Index: clang/test/Modules/InheritDefaultArguments.cppm
===================================================================
--- clang/test/Modules/InheritDefaultArguments.cppm
+++ clang/test/Modules/InheritDefaultArguments.cppm
@@ -2,8 +2,8 @@
// RUN: split-file %s %t
// RUN: cd %t
//
-// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only
+// RUN: %clang -std=c++20 %t/A.cppm --precompile -o %t/A.pcm
+// RUN: %clang -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -Xclang -verify -S -o -
//--- foo.h
template <typename T, typename U = int>
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -2643,46 +2643,6 @@
return false;
}
-static bool hasSameDefaultTemplateArgument(NamedDecl *X, NamedDecl *Y) {
- ASTContext &C = X->getASTContext();
- // If the type parameter isn't the same already, we don't need to check the
- // default argument further.
- if (!C.isSameTemplateParameter(X, Y))
- return false;
-
- if (auto *TTPX = dyn_cast<TemplateTypeParmDecl>(X)) {
- auto *TTPY = cast<TemplateTypeParmDecl>(Y);
- if (!TTPX->hasDefaultArgument() || !TTPY->hasDefaultArgument())
- return false;
-
- return C.hasSameType(TTPX->getDefaultArgument(),
- TTPY->getDefaultArgument());
- }
-
- if (auto *NTTPX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
- auto *NTTPY = cast<NonTypeTemplateParmDecl>(Y);
- if (!NTTPX->hasDefaultArgument() || !NTTPY->hasDefaultArgument())
- return false;
-
- Expr *DefaultArgumentX = NTTPX->getDefaultArgument()->IgnoreImpCasts();
- Expr *DefaultArgumentY = NTTPY->getDefaultArgument()->IgnoreImpCasts();
- llvm::FoldingSetNodeID XID, YID;
- DefaultArgumentX->Profile(XID, C, /*Canonical=*/true);
- DefaultArgumentY->Profile(YID, C, /*Canonical=*/true);
- return XID == YID;
- }
-
- auto *TTPX = cast<TemplateTemplateParmDecl>(X);
- auto *TTPY = cast<TemplateTemplateParmDecl>(Y);
-
- if (!TTPX->hasDefaultArgument() || !TTPY->hasDefaultArgument())
- return false;
-
- const TemplateArgument &TAX = TTPX->getDefaultArgument().getArgument();
- const TemplateArgument &TAY = TTPY->getDefaultArgument().getArgument();
- return C.hasSameTemplateName(TAX.getAsTemplate(), TAY.getAsTemplate());
-}
-
/// Checks the validity of a template parameter list, possibly
/// considering the template parameter list from a previous
/// declaration.
@@ -2780,7 +2740,8 @@
if (!OldTypeParm->getOwningModule() ||
isModuleUnitOfCurrentTU(OldTypeParm->getOwningModule()))
RedundantDefaultArg = true;
- else if (!hasSameDefaultTemplateArgument(OldTypeParm, NewTypeParm)) {
+ else if (!getASTContext().isSameDefaultTemplateArgument(OldTypeParm,
+ NewTypeParm)) {
InconsistentDefaultArg = true;
PrevModuleName =
OldTypeParm->getImportedOwningModule()->getFullModuleName();
@@ -2832,8 +2793,8 @@
if (!OldNonTypeParm->getOwningModule() ||
isModuleUnitOfCurrentTU(OldNonTypeParm->getOwningModule()))
RedundantDefaultArg = true;
- else if (!hasSameDefaultTemplateArgument(OldNonTypeParm,
- NewNonTypeParm)) {
+ else if (!getASTContext().isSameDefaultTemplateArgument(
+ OldNonTypeParm, NewNonTypeParm)) {
InconsistentDefaultArg = true;
PrevModuleName =
OldNonTypeParm->getImportedOwningModule()->getFullModuleName();
@@ -2884,8 +2845,8 @@
if (!OldTemplateParm->getOwningModule() ||
isModuleUnitOfCurrentTU(OldTemplateParm->getOwningModule()))
RedundantDefaultArg = true;
- else if (!hasSameDefaultTemplateArgument(OldTemplateParm,
- NewTemplateParm)) {
+ else if (!getASTContext().isSameDefaultTemplateArgument(
+ OldTemplateParm, NewTemplateParm)) {
InconsistentDefaultArg = true;
PrevModuleName =
OldTemplateParm->getImportedOwningModule()->getFullModuleName();
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -6294,6 +6294,45 @@
return true;
}
+bool ASTContext::isSameDefaultTemplateArgument(const NamedDecl *X,
+ const NamedDecl *Y) const {
+ // If the type parameter isn't the same already, we don't need to check the
+ // default argument further.
+ if (!isSameTemplateParameter(X, Y))
+ return false;
+
+ if (auto *TTPX = dyn_cast<TemplateTypeParmDecl>(X)) {
+ auto *TTPY = cast<TemplateTypeParmDecl>(Y);
+ if (!TTPX->hasDefaultArgument() || !TTPY->hasDefaultArgument())
+ return false;
+
+ return hasSameType(TTPX->getDefaultArgument(), TTPY->getDefaultArgument());
+ }
+
+ if (auto *NTTPX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
+ auto *NTTPY = cast<NonTypeTemplateParmDecl>(Y);
+ if (!NTTPX->hasDefaultArgument() || !NTTPY->hasDefaultArgument())
+ return false;
+
+ Expr *DefaultArgumentX = NTTPX->getDefaultArgument()->IgnoreImpCasts();
+ Expr *DefaultArgumentY = NTTPY->getDefaultArgument()->IgnoreImpCasts();
+ llvm::FoldingSetNodeID XID, YID;
+ DefaultArgumentX->Profile(XID, *this, /*Canonical=*/true);
+ DefaultArgumentY->Profile(YID, *this, /*Canonical=*/true);
+ return XID == YID;
+ }
+
+ auto *TTPX = cast<TemplateTemplateParmDecl>(X);
+ auto *TTPY = cast<TemplateTemplateParmDecl>(Y);
+
+ if (!TTPX->hasDefaultArgument() || !TTPY->hasDefaultArgument())
+ return false;
+
+ const TemplateArgument &TAX = TTPX->getDefaultArgument().getArgument();
+ const TemplateArgument &TAY = TTPY->getDefaultArgument().getArgument();
+ return hasSameTemplateName(TAX.getAsTemplate(), TAY.getAsTemplate());
+}
+
static NamespaceDecl *getNamespace(const NestedNameSpecifier *X) {
if (auto *NS = X->getAsNamespace())
return NS;
Index: clang/include/clang/AST/DeclTemplate.h
===================================================================
--- clang/include/clang/AST/DeclTemplate.h
+++ clang/include/clang/AST/DeclTemplate.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECLTEMPLATE_H
#include "clang/AST/ASTConcept.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
@@ -373,11 +374,19 @@
/// Set that the default argument was inherited from another parameter.
void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) {
- assert(!isInherited() && "default argument already inherited");
InheritedFrom = getParmOwningDefaultArg(InheritedFrom);
if (!isSet())
ValueOrInherited = InheritedFrom;
- else
+ else if (auto *D = ValueOrInherited.template dyn_cast<ParmDecl *>()) {
+ assert(C.isSameDefaultTemplateArgument(D, InheritedFrom));
+ ValueOrInherited =
+ new (allocateDefaultArgStorageChain(C)) Chain{InheritedFrom, get()};
+ } else if (auto *Inherited =
+ ValueOrInherited.template dyn_cast<Chain *>()) {
+ assert(C.isSameDefaultTemplateArgument(Inherited->PrevDeclWithDefaultArg,
+ InheritedFrom));
+ Inherited->PrevDeclWithDefaultArg = InheritedFrom;
+ } else
ValueOrInherited = new (allocateDefaultArgStorageChain(C))
Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()};
}
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -2664,6 +2664,11 @@
/// that they may be used in declarations of the same template.
bool isSameTemplateParameter(const NamedDecl *X, const NamedDecl *Y) const;
+ /// Determine whether two default template arguments are similar enough
+ /// that they may be used in declarations of the same template.
+ bool isSameDefaultTemplateArgument(const NamedDecl *X,
+ const NamedDecl *Y) const;
+
/// Retrieve the "canonical" template argument.
///
/// The canonical template argument is the simplest template argument
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits