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

Reply via email to