From: Richard Smith Date: Tue, 18 Oct 2016 20:13:25 +0000 (+0000) Subject: [c++1z] Fix corner case where we could create a function type whose canonical type... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f4c3280c90d6d2c38520f3587510cc6d03e1003c;p=clang [c++1z] Fix corner case where we could create a function type whose canonical type is not actually canonical. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@284528 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 3d777524b8..f914dae716 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1224,8 +1224,17 @@ public: /// \brief Return a normal function type with a typed argument list. QualType getFunctionType(QualType ResultTy, ArrayRef 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 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, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 0ac1e174fd..6b428839cf 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3167,9 +3167,9 @@ static bool isCanonicalExceptionSpecification( return false; } -QualType -ASTContext::getFunctionType(QualType ResultTy, ArrayRef ArgArray, - const FunctionProtoType::ExtProtoInfo &EPI) const { +QualType ASTContext::getFunctionTypeInternal( + QualType ResultTy, ArrayRef 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 ResultTy, ArrayRef ArgArray, // 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 ResultTy, ArrayRef ArgArray, 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 ResultTy, ArrayRef ArgArray, 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 = diff --git a/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/test/SemaCXX/cxx1z-noexcept-function-type.cpp index 711e0bca8b..7358c7de0b 100644 --- a/test/SemaCXX/cxx1z-noexcept-function-type.cpp +++ b/test/SemaCXX/cxx1z-noexcept-function-type.cpp @@ -12,6 +12,10 @@ template void redecl2() noexcept(B); // expected-error {{conflic template void redecl3() throw(A); template void redecl3() throw(B); +typedef int I; +template void redecl4(I) noexcept(B); +template void redecl4(I) noexcept(B); + namespace DependentDefaultCtorExceptionSpec { template struct T { static const bool value = true; };