Author: rsmith Date: Tue Oct 18 15:13:25 2016 New Revision: 284528 URL: http://llvm.org/viewvc/llvm-project?rev=284528&view=rev Log: [c++1z] Fix corner case where we could create a function type whose canonical type is not actually canonical.
Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/test/SemaCXX/cxx1z-noexcept-function-type.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=284528&r1=284527&r2=284528&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Tue Oct 18 15:13:25 2016 @@ -1224,8 +1224,17 @@ public: /// \brief Return a normal function type with a typed argument list. QualType getFunctionType(QualType ResultTy, ArrayRef<QualType> Args, - const FunctionProtoType::ExtProtoInfo &EPI) const; + const FunctionProtoType::ExtProtoInfo &EPI) const { + return getFunctionTypeInternal(ResultTy, Args, EPI, false); + } +private: + /// \brief Return a normal function type with a typed argument list. + QualType getFunctionTypeInternal(QualType ResultTy, ArrayRef<QualType> Args, + const FunctionProtoType::ExtProtoInfo &EPI, + bool OnlyWantCanonical) const; + +public: /// \brief Return the unique reference to the type for the specified type /// declaration. QualType getTypeDeclType(const TypeDecl *Decl, Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=284528&r1=284527&r2=284528&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Tue Oct 18 15:13:25 2016 @@ -3167,9 +3167,9 @@ static bool isCanonicalExceptionSpecific return false; } -QualType -ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, - const FunctionProtoType::ExtProtoInfo &EPI) const { +QualType ASTContext::getFunctionTypeInternal( + QualType ResultTy, ArrayRef<QualType> ArgArray, + const FunctionProtoType::ExtProtoInfo &EPI, bool OnlyWantCanonical) const { size_t NumArgs = ArgArray.size(); // Unique functions, to guarantee there is only one function of a particular @@ -3188,9 +3188,10 @@ ASTContext::getFunctionType(QualType Res // If we find a pre-existing equivalent FunctionProtoType, we can just reuse // it so long as our exception specification doesn't contain a dependent - // noexcept expression. If it /does/, we're going to need to create a type + // noexcept expression, or we're just looking for a canonical type. + // Otherwise, we're going to need to create a type // sugar node to hold the concrete expression. - if (EPI.ExceptionSpec.Type != EST_ComputedNoexcept || + if (OnlyWantCanonical || EPI.ExceptionSpec.Type != EST_ComputedNoexcept || EPI.ExceptionSpec.NoexceptExpr == FPT->getNoexceptExpr()) return Existing; @@ -3212,6 +3213,10 @@ ASTContext::getFunctionType(QualType Res if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; + if (OnlyWantCanonical) + assert(isCanonical && + "given non-canonical parameters constructing canonical type"); + // If this type isn't canonical, get the canonical version of it if we don't // already have it. The exception spec is only partially part of the // canonical type, and only in C++17 onwards. @@ -3274,15 +3279,14 @@ ASTContext::getFunctionType(QualType Res Value.getBoolValue() ? EST_BasicNoexcept : EST_None; break; } - assert(isCanonicalExceptionSpecification(CanonicalEPI.ExceptionSpec, - NoexceptInType)); } else { CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); } // Adjust the canonical function result type. CanQualType CanResultTy = getCanonicalFunctionResultType(ResultTy); - Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI); + Canonical = + getFunctionTypeInternal(CanResultTy, CanonicalArgs, CanonicalEPI, true); // Get the new insert position for the node we care about. FunctionProtoType *NewIP = Modified: cfe/trunk/test/SemaCXX/cxx1z-noexcept-function-type.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-noexcept-function-type.cpp?rev=284528&r1=284527&r2=284528&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1z-noexcept-function-type.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1z-noexcept-function-type.cpp Tue Oct 18 15:13:25 2016 @@ -12,6 +12,10 @@ template<bool A, bool B> void redecl2() template<typename A, typename B> void redecl3() throw(A); template<typename A, typename B> void redecl3() throw(B); +typedef int I; +template<bool B> void redecl4(I) noexcept(B); +template<bool B> void redecl4(I) noexcept(B); + namespace DependentDefaultCtorExceptionSpec { template<typename> struct T { static const bool value = true; }; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits