llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Vlad Serebrennikov (Endilll) <details> <summary>Changes</summary> This patch moves `Sema` functions that handle exception specification into the new `SemaExceptionSpec` class. This continues previous efforts to split `Sema` up. Additional context can be found in https://github.com/llvm/llvm-project/pull/84184. I also moved several exception specification-related function from `SemaDeclCXX.cpp` to `SemaExceptionSpec`, but not all of them. The rest rely on TU-local entities in `SemaDeclCXX.cpp` that are shared with the code not related to exception specification. As usual, in order to help reviewing this, formatting changes are split into a separate commit. --- Patch is 107.86 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/92653.diff 21 Files Affected: - (modified) clang/include/clang/Sema/Sema.h (+28-159) - (added) clang/include/clang/Sema/SemaExceptionSpec.h (+187) - (modified) clang/lib/Parse/ParseCXXInlineMethods.cpp (+5-6) - (modified) clang/lib/Parse/ParseDecl.cpp (+3-1) - (modified) clang/lib/Parse/ParseDeclCXX.cpp (+3-2) - (modified) clang/lib/Sema/AnalysisBasedWarnings.cpp (+4-2) - (modified) clang/lib/Sema/Sema.cpp (+7-5) - (modified) clang/lib/Sema/SemaCoroutine.cpp (+3-1) - (modified) clang/lib/Sema/SemaDecl.cpp (+7-6) - (modified) clang/lib/Sema/SemaDeclCXX.cpp (+26-206) - (modified) clang/lib/Sema/SemaExceptionSpec.cpp (+350-106) - (modified) clang/lib/Sema/SemaExpr.cpp (+4-2) - (modified) clang/lib/Sema/SemaExprCXX.cpp (+14-12) - (modified) clang/lib/Sema/SemaExprMember.cpp (+3-1) - (modified) clang/lib/Sema/SemaInit.cpp (+5-2) - (modified) clang/lib/Sema/SemaOverload.cpp (+4-3) - (modified) clang/lib/Sema/SemaTemplate.cpp (+4-2) - (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+29-1) - (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+6-4) - (modified) clang/lib/Sema/SemaType.cpp (+12-11) - (modified) clang/lib/Sema/TreeTransform.h (+6-3) ``````````diff diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d4d4a82525a02..95a54014cf672 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -169,6 +169,7 @@ class PseudoObjectExpr; class QualType; class SemaCodeCompletion; class SemaCUDA; +class SemaExceptionSpec; class SemaHLSL; class SemaObjC; class SemaOpenACC; @@ -461,29 +462,28 @@ class Sema final : public SemaBase { // 9. Declarations (SemaDecl.cpp) // 10. Declaration Attribute Handling (SemaDeclAttr.cpp) // 11. C++ Declarations (SemaDeclCXX.cpp) - // 12. C++ Exception Specifications (SemaExceptionSpec.cpp) - // 13. Expressions (SemaExpr.cpp) - // 14. C++ Expressions (SemaExprCXX.cpp) - // 15. Member Access Expressions (SemaExprMember.cpp) - // 16. Initializers (SemaInit.cpp) - // 17. C++ Lambda Expressions (SemaLambda.cpp) - // 18. Name Lookup (SemaLookup.cpp) - // 19. Modules (SemaModule.cpp) - // 20. C++ Overloading (SemaOverload.cpp) - // 21. Pseudo-Object (SemaPseudoObject.cpp) - // 22. Statements (SemaStmt.cpp) - // 23. `inline asm` Statement (SemaStmtAsm.cpp) - // 24. Statement Attribute Handling (SemaStmtAttr.cpp) - // 25. C++ Templates (SemaTemplate.cpp) - // 26. C++ Template Argument Deduction (SemaTemplateDeduction.cpp) - // 27. C++ Template Instantiation (SemaTemplateInstantiate.cpp) - // 28. C++ Template Declaration Instantiation + // 12. Expressions (SemaExpr.cpp) + // 13. C++ Expressions (SemaExprCXX.cpp) + // 14. Member Access Expressions (SemaExprMember.cpp) + // 15. Initializers (SemaInit.cpp) + // 16. C++ Lambda Expressions (SemaLambda.cpp) + // 17. Name Lookup (SemaLookup.cpp) + // 18. Modules (SemaModule.cpp) + // 19. C++ Overloading (SemaOverload.cpp) + // 20. Pseudo-Object (SemaPseudoObject.cpp) + // 21. Statements (SemaStmt.cpp) + // 22. `inline asm` Statement (SemaStmtAsm.cpp) + // 23. Statement Attribute Handling (SemaStmtAttr.cpp) + // 24. C++ Templates (SemaTemplate.cpp) + // 25. C++ Template Argument Deduction (SemaTemplateDeduction.cpp) + // 26. C++ Template Instantiation (SemaTemplateInstantiate.cpp) + // 27. C++ Template Declaration Instantiation // (SemaTemplateInstantiateDecl.cpp) - // 29. C++ Variadic Templates (SemaTemplateVariadic.cpp) - // 30. Constraints and Concepts (SemaConcept.cpp) - // 31. Types (SemaType.cpp) - // 32. FixIt Helpers (SemaFixItUtils.cpp) - // 33. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) + // 28. C++ Variadic Templates (SemaTemplateVariadic.cpp) + // 29. Constraints and Concepts (SemaConcept.cpp) + // 30. Types (SemaType.cpp) + // 31. FixIt Helpers (SemaFixItUtils.cpp) + // 32. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -994,6 +994,11 @@ class Sema final : public SemaBase { return *CUDAPtr; } + SemaExceptionSpec &ExceptionSpec() { + assert(ExceptionSpecPtr); + return *ExceptionSpecPtr; + } + SemaHLSL &HLSL() { assert(HLSLPtr); return *HLSLPtr; @@ -1051,6 +1056,7 @@ class Sema final : public SemaBase { std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr; std::unique_ptr<SemaCUDA> CUDAPtr; + std::unique_ptr<SemaExceptionSpec> ExceptionSpecPtr; std::unique_ptr<SemaHLSL> HLSLPtr; std::unique_ptr<SemaObjC> ObjCPtr; std::unique_ptr<SemaOpenACC> OpenACCPtr; @@ -4048,25 +4054,6 @@ class Sema final : public SemaBase { /// Evaluate the implicit exception specification for a defaulted /// special member function. void EvaluateImplicitExceptionSpec(SourceLocation Loc, FunctionDecl *FD); - - /// Check the given exception-specification and update the - /// exception specification information with the results. - void checkExceptionSpecification(bool IsTopLevel, - ExceptionSpecificationType EST, - ArrayRef<ParsedType> DynamicExceptions, - ArrayRef<SourceRange> DynamicExceptionRanges, - Expr *NoexceptExpr, - SmallVectorImpl<QualType> &Exceptions, - FunctionProtoType::ExceptionSpecInfo &ESI); - - /// Add an exception-specification to the given member or friend function - /// (or function template). The exception-specification was parsed - /// after the function itself was declared. - void actOnDelayedExceptionSpecification( - Decl *D, ExceptionSpecificationType EST, SourceRange SpecificationRange, - ArrayRef<ParsedType> DynamicExceptions, - ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr); - class InheritedConstructorInfo; /// Determine if a special member function should have a deleted @@ -4105,12 +4092,6 @@ class Sema final : public SemaBase { void DefineImplicitDestructor(SourceLocation CurrentLocation, CXXDestructorDecl *Destructor); - /// Build an exception spec for destructors that don't have one. - /// - /// C++11 says that user-defined destructors with no exception spec get one - /// that looks as if the destructor was implicitly declared. - void AdjustDestructorExceptionSpec(CXXDestructorDecl *Destructor); - /// Define the specified inheriting constructor. void DefineInheritingConstructor(SourceLocation UseLoc, CXXConstructorDecl *Constructor); @@ -4346,11 +4327,6 @@ class Sema final : public SemaBase { void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, bool DefinitionRequired = false); - /// Mark the exception specifications of all virtual member functions - /// in the given class as needed. - void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc, - const CXXRecordDecl *RD); - /// MarkVirtualMembersReferenced - Will mark all members of the given /// CXXRecordDecl referenced. void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD, @@ -4437,7 +4413,6 @@ class Sema final : public SemaBase { bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, SourceLocation DefaultLoc); - void CheckDelayedMemberExceptionSpecs(); /// Kinds of defaulted comparison operator functions. enum class DefaultedComparisonKind : unsigned char { @@ -4588,7 +4563,6 @@ class Sema final : public SemaBase { SmallVector<CXXRecordDecl *, 4> DelayedDllExportClasses; SmallVector<CXXMethodDecl *, 4> DelayedDllExportMemberFunctions; - void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); /// Helpers for dealing with blocks and functions. @@ -4836,84 +4810,6 @@ class Sema final : public SemaBase { // // - /// \name C++ Exception Specifications - /// Implementations are in SemaExceptionSpec.cpp - ///@{ - -public: - /// All the overriding functions seen during a class definition - /// that had their exception spec checks delayed, plus the overridden - /// function. - SmallVector<std::pair<const CXXMethodDecl *, const CXXMethodDecl *>, 2> - DelayedOverridingExceptionSpecChecks; - - /// All the function redeclarations seen during a class definition that had - /// their exception spec checks delayed, plus the prior declaration they - /// should be checked against. Except during error recovery, the new decl - /// should always be a friend declaration, as that's the only valid way to - /// redeclare a special member before its class is complete. - SmallVector<std::pair<FunctionDecl *, FunctionDecl *>, 2> - DelayedEquivalentExceptionSpecChecks; - - /// Determine if we're in a case where we need to (incorrectly) eagerly - /// parse an exception specification to work around a libstdc++ bug. - bool isLibstdcxxEagerExceptionSpecHack(const Declarator &D); - - /// Check the given noexcept-specifier, convert its expression, and compute - /// the appropriate ExceptionSpecificationType. - ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr, - ExceptionSpecificationType &EST); - - CanThrowResult canThrow(const Stmt *E); - /// Determine whether the callee of a particular function call can throw. - /// E, D and Loc are all optional. - static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D, - SourceLocation Loc = SourceLocation()); - const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc, - const FunctionProtoType *FPT); - void UpdateExceptionSpec(FunctionDecl *FD, - const FunctionProtoType::ExceptionSpecInfo &ESI); - bool CheckSpecifiedExceptionType(QualType &T, SourceRange Range); - bool CheckDistantExceptionSpec(QualType T); - bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); - bool CheckEquivalentExceptionSpec(const FunctionProtoType *Old, - SourceLocation OldLoc, - const FunctionProtoType *New, - SourceLocation NewLoc); - bool CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, - const PartialDiagnostic &NoteID, - const FunctionProtoType *Old, - SourceLocation OldLoc, - const FunctionProtoType *New, - SourceLocation NewLoc); - bool handlerCanCatch(QualType HandlerType, QualType ExceptionType); - bool CheckExceptionSpecSubset( - const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID, - const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID, - const FunctionProtoType *Superset, bool SkipSupersetFirstParameter, - SourceLocation SuperLoc, const FunctionProtoType *Subset, - bool SkipSubsetFirstParameter, SourceLocation SubLoc); - bool CheckParamExceptionSpec( - const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID, - const FunctionProtoType *Target, bool SkipTargetFirstParameter, - SourceLocation TargetLoc, const FunctionProtoType *Source, - bool SkipSourceFirstParameter, SourceLocation SourceLoc); - - bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType); - - /// CheckOverridingFunctionExceptionSpec - Checks whether the exception - /// spec is a subset of base spec. - bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, - const CXXMethodDecl *Old); - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - /// \name Expressions /// Implementations are in SemaExpr.cpp ///@{ @@ -10654,33 +10550,6 @@ class Sema final : public SemaBase { int ParsingClassDepth = 0; - class SavePendingParsedClassStateRAII { - public: - SavePendingParsedClassStateRAII(Sema &S) : S(S) { swapSavedState(); } - - ~SavePendingParsedClassStateRAII() { - assert(S.DelayedOverridingExceptionSpecChecks.empty() && - "there shouldn't be any pending delayed exception spec checks"); - assert(S.DelayedEquivalentExceptionSpecChecks.empty() && - "there shouldn't be any pending delayed exception spec checks"); - swapSavedState(); - } - - private: - Sema &S; - decltype(DelayedOverridingExceptionSpecChecks) - SavedOverridingExceptionSpecChecks; - decltype(DelayedEquivalentExceptionSpecChecks) - SavedEquivalentExceptionSpecChecks; - - void swapSavedState() { - SavedOverridingExceptionSpecChecks.swap( - S.DelayedOverridingExceptionSpecChecks); - SavedEquivalentExceptionSpecChecks.swap( - S.DelayedEquivalentExceptionSpecChecks); - } - }; - ///@} // diff --git a/clang/include/clang/Sema/SemaExceptionSpec.h b/clang/include/clang/Sema/SemaExceptionSpec.h new file mode 100644 index 0000000000000..17d505e977889 --- /dev/null +++ b/clang/include/clang/Sema/SemaExceptionSpec.h @@ -0,0 +1,187 @@ +//===--- SemaExceptionSpec.h --- C++ exception specification ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares routines for C++ exception specification testing. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMAEXCEPTIONSPEC_H +#define LLVM_CLANG_SEMA_SEMAEXCEPTIONSPEC_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "clang/Basic/ExceptionSpecificationType.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Ownership.h" +#include "clang/Sema/SemaBase.h" +#include "llvm/ADT/SmallPtrSet.h" +#include <utility> + +namespace clang { +class SemaExceptionSpec : public SemaBase { +public: + SemaExceptionSpec(Sema &S); + + /// All the overriding functions seen during a class definition + /// that had their exception spec checks delayed, plus the overridden + /// function. + SmallVector<std::pair<const CXXMethodDecl *, const CXXMethodDecl *>, 2> + DelayedOverridingExceptionSpecChecks; + + /// All the function redeclarations seen during a class definition that had + /// their exception spec checks delayed, plus the prior declaration they + /// should be checked against. Except during error recovery, the new decl + /// should always be a friend declaration, as that's the only valid way to + /// redeclare a special member before its class is complete. + SmallVector<std::pair<FunctionDecl *, FunctionDecl *>, 2> + DelayedEquivalentExceptionSpecChecks; + + /// Determine if we're in a case where we need to (incorrectly) eagerly + /// parse an exception specification to work around a libstdc++ bug. + bool isLibstdcxxEagerExceptionSpecHack(const Declarator &D); + + /// Check the given noexcept-specifier, convert its expression, and compute + /// the appropriate ExceptionSpecificationType. + ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr, + ExceptionSpecificationType &EST); + + CanThrowResult canThrow(const Stmt *E); + /// Determine whether the callee of a particular function call can throw. + /// E, D and Loc are all optional. + static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D, + SourceLocation Loc = SourceLocation()); + const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc, + const FunctionProtoType *FPT); + void UpdateExceptionSpec(FunctionDecl *FD, + const FunctionProtoType::ExceptionSpecInfo &ESI); + bool CheckSpecifiedExceptionType(QualType &T, SourceRange Range); + bool CheckDistantExceptionSpec(QualType T); + bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); + bool CheckEquivalentExceptionSpec(const FunctionProtoType *Old, + SourceLocation OldLoc, + const FunctionProtoType *New, + SourceLocation NewLoc); + bool CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, + const PartialDiagnostic &NoteID, + const FunctionProtoType *Old, + SourceLocation OldLoc, + const FunctionProtoType *New, + SourceLocation NewLoc); + bool handlerCanCatch(QualType HandlerType, QualType ExceptionType); + bool CheckExceptionSpecSubset( + const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID, + const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID, + const FunctionProtoType *Superset, bool SkipSupersetFirstParameter, + SourceLocation SuperLoc, const FunctionProtoType *Subset, + bool SkipSubsetFirstParameter, SourceLocation SubLoc); + bool CheckParamExceptionSpec( + const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID, + const FunctionProtoType *Target, bool SkipTargetFirstParameter, + SourceLocation TargetLoc, const FunctionProtoType *Source, + bool SkipSourceFirstParameter, SourceLocation SourceLoc); + + bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType); + + /// CheckOverridingFunctionExceptionSpec - Checks whether the exception + /// spec is a subset of base spec. + bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, + const CXXMethodDecl *Old); + + void CheckDelayedMemberExceptionSpecs(); + + /// Helper class that collects exception specifications for + /// implicitly-declared special member functions. + class ImplicitExceptionSpecification { + // Pointer to allow copying + Sema *Self; + // We order exception specifications thus: + // noexcept is the most restrictive, but is only used in C++11. + // throw() comes next. + // Then a throw(collected exceptions) + // Finally no specification, which is expressed as noexcept(false). + // throw(...) is used instead if any called function uses it. + ExceptionSpecificationType ComputedEST; + llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen; + SmallVector<QualType, 4> Exceptions; + + void ClearExceptions() { + ExceptionsSeen.clear(); + Exceptions.clear(); + } + + public: + explicit ImplicitExceptionSpecification(Sema &Self); + + /// Get the computed exception specification type. + ExceptionSpecificationType getExceptionSpecType() const { + assert(!isComputedNoexcept(ComputedEST) && + "noexcept(expr) should not be a possible result"); + return ComputedEST; + } + + /// The number of exceptions in the exception specification. + unsigned size() const { return Exceptions.size(); } + + /// The set of exceptions in the exception specification. + const QualType *data() const { return Exceptions.data(); } + + /// Integrate another called method into the collected data. + void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method); + + /// Integrate an invoked expression into the collected data. + void CalledExpr(Expr *E) { CalledStmt(E); } + + /// Integrate an invoked statement into the collected data. + void CalledStmt(Stmt *S); + + /// Overwrite an EPI's exception specification with this + /// computed exception specification. + FunctionProtoType::ExceptionSpecInfo getExceptionSpec() const; + }; + + /// Check the given exception-specification and update the + /// exception specification information with the results. + void checkExceptionSpecification(bool IsTopLevel, + ExceptionSpecificationType EST, + ArrayRef<ParsedType> DynamicExceptions, + ArrayRef<SourceRange> DynamicExceptionRanges, + Expr *NoexceptExpr, + SmallVectorImpl<QualType> &Exceptions, + FunctionProtoType::ExceptionSpecInfo &ESI); + + /// Add an exception-specification to the given member or friend function + /// (or function template). The exception-specification was parsed + /// after the function itself was declared. + void actOnDelayedExceptionSpecification( + Decl *D, ExceptionSpecificationType EST, SourceRange SpecificationRange, + ArrayRef<ParsedType> DynamicExceptions, + ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr); + + /// Build an exception spec for destructors that don't ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/92653 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits