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()); -} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits