[clang] 55b6f68 - Revert "Fix rejects-valid when referencing an implicit operator== from within a"
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 17 16:05:40 PDT 2020
Author: Richard Smith
Date: 2020-06-17T16:05:26-07:00
New Revision: 55b6f68f4b254bd1506ff844fa511b6658607992
URL: https://github.com/llvm/llvm-project/commit/55b6f68f4b254bd1506ff844fa511b6658607992
DIFF: https://github.com/llvm/llvm-project/commit/55b6f68f4b254bd1506ff844fa511b6658607992.diff
LOG: Revert "Fix rejects-valid when referencing an implicit operator== from within a"
This change may have caused some self-host failures. Reverting while
investigating.
This reverts commit c7fbe2191b8b9cd64570ed3906d1bed1dd5fff8e.
Added:
Modified:
clang/include/clang/AST/DeclBase.h
clang/include/clang/Sema/Template.h
clang/lib/AST/DeclBase.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/PCH/cxx2a-defaulted-comparison.cpp
Removed:
clang/test/SemaTemplate/defaulted.cpp
################################################################################
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 5e00be35d8ce..ba84f27617f5 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -66,7 +66,6 @@ class SourceManager;
class Stmt;
class StoredDeclsMap;
class TemplateDecl;
-class TemplateParameterList;
class TranslationUnitDecl;
class UsingDirectiveDecl;
@@ -863,10 +862,6 @@ class alignas(8) Decl {
// within the scope of a template parameter).
bool isTemplated() const;
- /// Determine the number of levels of template parameter surrounding this
- /// declaration.
- unsigned getTemplateDepth() const;
-
/// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
/// scoped decl is defined outside the current function or method. This is
/// roughly global variables and functions, but also handles enums (which
@@ -1043,16 +1038,8 @@ class alignas(8) Decl {
/// If this is a declaration that describes some template, this
/// method returns that template declaration.
- ///
- /// Note that this returns nullptr for partial specializations, because they
- /// are not modeled as TemplateDecls. Use getDescribedTemplateParams to handle
- /// those cases.
TemplateDecl *getDescribedTemplate() const;
- /// If this is a declaration that describes some template or partial
- /// specialization, this returns the corresponding template parameter list.
- const TemplateParameterList *getDescribedTemplateParams() const;
-
/// Returns the function itself, or the templated function if this is a
/// function template.
FunctionDecl *getAsFunction() LLVM_READONLY;
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index d05c3a55f89c..8166b6cf9b6f 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -95,10 +95,6 @@ class VarDecl;
return TemplateArgumentLists.size();
}
- unsigned getNumRetainedOuterLevels() const {
- return NumRetainedOuterLevels;
- }
-
/// Determine how many of the \p OldDepth outermost template parameter
/// lists would be removed by substituting these arguments.
unsigned getNewDepth(unsigned OldDepth) const {
@@ -163,9 +159,6 @@ class VarDecl;
void addOuterRetainedLevel() {
++NumRetainedOuterLevels;
}
- void addOuterRetainedLevels(unsigned Num) {
- NumRetainedOuterLevels += Num;
- }
/// Retrieve the innermost template argument list.
const ArgList &getInnermost() const {
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index a9cd7918da9b..2aab53f4fa90 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -240,16 +240,6 @@ TemplateDecl *Decl::getDescribedTemplate() const {
return nullptr;
}
-const TemplateParameterList *Decl::getDescribedTemplateParams() const {
- if (auto *TD = getDescribedTemplate())
- return TD->getTemplateParameters();
- if (auto *CTPSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(this))
- return CTPSD->getTemplateParameters();
- if (auto *VTPSD = dyn_cast<VarTemplatePartialSpecializationDecl>(this))
- return VTPSD->getTemplateParameters();
- return nullptr;
-}
-
bool Decl::isTemplated() const {
// A declaration is dependent if it is a template or a template pattern, or
// is within (lexcially for a friend, semantically otherwise) a dependent
@@ -258,29 +248,7 @@ bool Decl::isTemplated() const {
if (auto *AsDC = dyn_cast<DeclContext>(this))
return AsDC->isDependentContext();
auto *DC = getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext();
- return DC->isDependentContext() || isTemplateDecl() ||
- getDescribedTemplateParams();
-}
-
-unsigned Decl::getTemplateDepth() const {
- if (auto *DC = dyn_cast<DeclContext>(this))
- if (DC->isFileContext())
- return 0;
-
- if (auto *TPL = getDescribedTemplateParams())
- return TPL->getDepth() + 1;
-
- // If this is a dependent lambda, there might be an enclosing variable
- // template. In this case, the next step is not the parent DeclContext (or
- // even a DeclContext at all).
- auto *RD = dyn_cast<CXXRecordDecl>(this);
- if (RD && RD->isDependentLambda())
- if (Decl *Context = RD->getLambdaContextDecl())
- return Context->getTemplateDepth();
-
- const DeclContext *DC =
- getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext();
- return cast<Decl>(DC)->getTemplateDepth();
+ return DC->isDependentContext() || isTemplateDecl() || getDescribedTemplate();
}
const DeclContext *Decl::getParentFunctionOrMethod() const {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f1da788b1209..80469e3bedbe 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -17170,10 +17170,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
I.setAccess((*I)->getAccess());
}
- // Add any implicitly-declared members to this class.
- AddImplicitlyDeclaredMembersToClass(CXXRecord);
-
if (!CXXRecord->isDependentType()) {
+ // Add any implicitly-declared members to this class.
+ AddImplicitlyDeclaredMembersToClass(CXXRecord);
+
if (!CXXRecord->isInvalidDecl()) {
// If we have virtual base classes, we may end up finding multiple
// final overriders for a given virtual function. Check for this
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index e38ea6d2bc08..a2b669c99125 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9839,95 +9839,86 @@ static void findImplicitlyDeclaredEqualityComparisons(
/// [special]p1). This routine can only be executed just before the
/// definition of the class is complete.
void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
- // Don't add implicit special members to templated classes.
- // FIXME: This means unqualified lookups for 'operator=' within a class
- // template don't work properly.
- if (!ClassDecl->isDependentType()) {
- if (ClassDecl->needsImplicitDefaultConstructor()) {
- ++getASTContext().NumImplicitDefaultConstructors;
+ if (ClassDecl->needsImplicitDefaultConstructor()) {
+ ++getASTContext().NumImplicitDefaultConstructors;
- if (ClassDecl->hasInheritedConstructor())
- DeclareImplicitDefaultConstructor(ClassDecl);
- }
+ if (ClassDecl->hasInheritedConstructor())
+ DeclareImplicitDefaultConstructor(ClassDecl);
+ }
- if (ClassDecl->needsImplicitCopyConstructor()) {
- ++getASTContext().NumImplicitCopyConstructors;
+ if (ClassDecl->needsImplicitCopyConstructor()) {
+ ++getASTContext().NumImplicitCopyConstructors;
- // If the properties or semantics of the copy constructor couldn't be
- // determined while the class was being declared, force a declaration
- // of it now.
- if (ClassDecl->needsOverloadResolutionForCopyConstructor() ||
- ClassDecl->hasInheritedConstructor())
- DeclareImplicitCopyConstructor(ClassDecl);
- // For the MS ABI we need to know whether the copy ctor is deleted. A
- // prerequisite for deleting the implicit copy ctor is that the class has
- // a move ctor or move assignment that is either user-declared or whose
- // semantics are inherited from a subobject. FIXME: We should provide a
- // more direct way for CodeGen to ask whether the constructor was deleted.
- else if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
- (ClassDecl->hasUserDeclaredMoveConstructor() ||
- ClassDecl->needsOverloadResolutionForMoveConstructor() ||
- ClassDecl->hasUserDeclaredMoveAssignment() ||
- ClassDecl->needsOverloadResolutionForMoveAssignment()))
- DeclareImplicitCopyConstructor(ClassDecl);
- }
+ // If the properties or semantics of the copy constructor couldn't be
+ // determined while the class was being declared, force a declaration
+ // of it now.
+ if (ClassDecl->needsOverloadResolutionForCopyConstructor() ||
+ ClassDecl->hasInheritedConstructor())
+ DeclareImplicitCopyConstructor(ClassDecl);
+ // For the MS ABI we need to know whether the copy ctor is deleted. A
+ // prerequisite for deleting the implicit copy ctor is that the class has a
+ // move ctor or move assignment that is either user-declared or whose
+ // semantics are inherited from a subobject. FIXME: We should provide a more
+ // direct way for CodeGen to ask whether the constructor was deleted.
+ else if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ (ClassDecl->hasUserDeclaredMoveConstructor() ||
+ ClassDecl->needsOverloadResolutionForMoveConstructor() ||
+ ClassDecl->hasUserDeclaredMoveAssignment() ||
+ ClassDecl->needsOverloadResolutionForMoveAssignment()))
+ DeclareImplicitCopyConstructor(ClassDecl);
+ }
- if (getLangOpts().CPlusPlus11 &&
- ClassDecl->needsImplicitMoveConstructor()) {
- ++getASTContext().NumImplicitMoveConstructors;
+ if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) {
+ ++getASTContext().NumImplicitMoveConstructors;
- if (ClassDecl->needsOverloadResolutionForMoveConstructor() ||
- ClassDecl->hasInheritedConstructor())
- DeclareImplicitMoveConstructor(ClassDecl);
- }
+ if (ClassDecl->needsOverloadResolutionForMoveConstructor() ||
+ ClassDecl->hasInheritedConstructor())
+ DeclareImplicitMoveConstructor(ClassDecl);
+ }
- if (ClassDecl->needsImplicitCopyAssignment()) {
- ++getASTContext().NumImplicitCopyAssignmentOperators;
+ if (ClassDecl->needsImplicitCopyAssignment()) {
+ ++getASTContext().NumImplicitCopyAssignmentOperators;
- // If we have a dynamic class, then the copy assignment operator may be
- // virtual, so we have to declare it immediately. This ensures that, e.g.,
- // it shows up in the right place in the vtable and that we diagnose
- // problems with the implicit exception specification.
- if (ClassDecl->isDynamicClass() ||
- ClassDecl->needsOverloadResolutionForCopyAssignment() ||
- ClassDecl->hasInheritedAssignment())
- DeclareImplicitCopyAssignment(ClassDecl);
- }
+ // If we have a dynamic class, then the copy assignment operator may be
+ // virtual, so we have to declare it immediately. This ensures that, e.g.,
+ // it shows up in the right place in the vtable and that we diagnose
+ // problems with the implicit exception specification.
+ if (ClassDecl->isDynamicClass() ||
+ ClassDecl->needsOverloadResolutionForCopyAssignment() ||
+ ClassDecl->hasInheritedAssignment())
+ DeclareImplicitCopyAssignment(ClassDecl);
+ }
- if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) {
- ++getASTContext().NumImplicitMoveAssignmentOperators;
+ if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) {
+ ++getASTContext().NumImplicitMoveAssignmentOperators;
- // Likewise for the move assignment operator.
- if (ClassDecl->isDynamicClass() ||
- ClassDecl->needsOverloadResolutionForMoveAssignment() ||
- ClassDecl->hasInheritedAssignment())
- DeclareImplicitMoveAssignment(ClassDecl);
- }
+ // Likewise for the move assignment operator.
+ if (ClassDecl->isDynamicClass() ||
+ ClassDecl->needsOverloadResolutionForMoveAssignment() ||
+ ClassDecl->hasInheritedAssignment())
+ DeclareImplicitMoveAssignment(ClassDecl);
+ }
- if (ClassDecl->needsImplicitDestructor()) {
- ++getASTContext().NumImplicitDestructors;
+ if (ClassDecl->needsImplicitDestructor()) {
+ ++getASTContext().NumImplicitDestructors;
- // If we have a dynamic class, then the destructor may be virtual, so we
- // have to declare the destructor immediately. This ensures that, e.g., it
- // shows up in the right place in the vtable and that we diagnose problems
- // with the implicit exception specification.
- if (ClassDecl->isDynamicClass() ||
- ClassDecl->needsOverloadResolutionForDestructor())
- DeclareImplicitDestructor(ClassDecl);
- }
+ // If we have a dynamic class, then the destructor may be virtual, so we
+ // have to declare the destructor immediately. This ensures that, e.g., it
+ // shows up in the right place in the vtable and that we diagnose problems
+ // with the implicit exception specification.
+ if (ClassDecl->isDynamicClass() ||
+ ClassDecl->needsOverloadResolutionForDestructor())
+ DeclareImplicitDestructor(ClassDecl);
}
// C++2a [class.compare.default]p3:
// If the member-specification does not explicitly declare any member or
// friend named operator==, an == operator function is declared implicitly
- // for each defaulted three-way comparison operator function defined in
- // the member-specification
+ // for each defaulted three-way comparison operator function defined in the
+ // member-specification
// FIXME: Consider doing this lazily.
- // We do this during the initial parse for a class template, not during
- // instantiation, so that we can handle unqualified lookups for 'operator=='
- // when parsing the template.
- if (getLangOpts().CPlusPlus20 && !inTemplateInstantiation()) {
- llvm::SmallVector<FunctionDecl *, 4> DefaultedSpaceships;
+ if (getLangOpts().CPlusPlus20) {
+ llvm::SmallVector<FunctionDecl*, 4> DefaultedSpaceships;
findImplicitlyDeclaredEqualityComparisons(Context, ClassDecl,
DefaultedSpaceships);
for (auto *FD : DefaultedSpaceships)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ee91c51e2046..7d0777cce6ae 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3719,7 +3719,6 @@ FunctionDecl *Sema::SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD,
// access and function-definition and in the same class scope as the
// three-way comparison operator function
MultiLevelTemplateArgumentList NoTemplateArgs;
- NoTemplateArgs.addOuterRetainedLevels(RD->getTemplateDepth());
TemplateDeclInstantiator Instantiator(*this, RD, NoTemplateArgs);
Decl *R;
if (auto *MD = dyn_cast<CXXMethodDecl>(Spaceship)) {
@@ -5606,20 +5605,6 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC,
} else return DC;
}
-/// Determine whether the given context is dependent on template parameters at
-/// level \p Level or below.
-///
-/// Sometimes we only substitute an inner set of template arguments and leave
-/// the outer templates alone. In such cases, contexts dependent only on the
-/// outer levels are not effectively dependent.
-static bool isDependentContextAtLevel(DeclContext *DC, unsigned Level) {
- if (!DC->isDependentContext())
- return false;
- if (!Level)
- return true;
- return cast<Decl>(DC)->getTemplateDepth() > Level;
-}
-
/// Find the instantiation of the given declaration within the
/// current instantiation.
///
@@ -5650,10 +5635,6 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool FindingInstantiatedContext) {
DeclContext *ParentDC = D->getDeclContext();
- // Determine whether our parent context depends on any of the tempalte
- // arguments we're currently substituting.
- bool ParentDependsOnArgs = isDependentContextAtLevel(
- ParentDC, TemplateArgs.getNumRetainedOuterLevels());
// FIXME: Parmeters of pointer to functions (y below) that are themselves
// parameters (p below) can have their ParentDC set to the translation-unit
// - thus we can not consistently check if the ParentDC of such a parameter
@@ -5670,14 +5651,15 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
// - as long as we have a ParmVarDecl whose parent is non-dependent and
// whose type is not instantiation dependent, do nothing to the decl
// - otherwise find its instantiated decl.
- if (isa<ParmVarDecl>(D) && !ParentDependsOnArgs &&
+ if (isa<ParmVarDecl>(D) && !ParentDC->isDependentContext() &&
!cast<ParmVarDecl>(D)->getType()->isInstantiationDependentType())
return D;
if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
- (ParentDependsOnArgs && (ParentDC->isFunctionOrMethod() ||
- isa<OMPDeclareReductionDecl>(ParentDC) ||
- isa<OMPDeclareMapperDecl>(ParentDC))) ||
+ ((ParentDC->isFunctionOrMethod() ||
+ isa<OMPDeclareReductionDecl>(ParentDC) ||
+ isa<OMPDeclareMapperDecl>(ParentDC)) &&
+ ParentDC->isDependentContext()) ||
(isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) {
// D is a local of some kind. Look into the map of local
// declarations to their instantiations.
@@ -5831,7 +5813,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
// anonymous unions in class templates).
}
- if (!ParentDependsOnArgs)
+ if (!ParentDC->isDependentContext())
return D;
ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs);
diff --git a/clang/test/PCH/cxx2a-defaulted-comparison.cpp b/clang/test/PCH/cxx2a-defaulted-comparison.cpp
index d771424ad4fb..4fb0b83b2648 100644
--- a/clang/test/PCH/cxx2a-defaulted-comparison.cpp
+++ b/clang/test/PCH/cxx2a-defaulted-comparison.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++2a -verify -Wno-defaulted-function-deleted -include %s %s
+// RxN: %clang_cc1 -std=c++2a -verify -Wno-defaulted-function-deleted -include %s %s
//
// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t.pch
// RUN: %clang_cc1 -std=c++2a -include-pch %t.pch %s -verify
diff --git a/clang/test/SemaTemplate/defaulted.cpp b/clang/test/SemaTemplate/defaulted.cpp
deleted file mode 100644
index 15111f71202d..000000000000
--- a/clang/test/SemaTemplate/defaulted.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 -verify %s
-// expected-no-diagnostics
-
-namespace SpaceshipImpliesEq {
- template<typename T> struct A {
- int operator<=>(const A&) const = default;
- constexpr bool f() { return operator==(*this); }
- };
- static_assert(A<int>().f());
-}
More information about the cfe-commits
mailing list