<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Sep 18, 2014 at 4:32 PM, Alexander Kornienko <span dir="ltr"><<a href="mailto:alexfh@google.com" target="_blank">alexfh@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class="">On Thu, Sep 18, 2014 at 1:57 AM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br></span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div class="h5">Author: rsmith<br>
Date: Wed Sep 17 18:57:05 2014<br>
New Revision: 217995<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=217995&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=217995&view=rev</a><br>
Log:<br>
Instantiate exception specifications when instantiating function types (other<br>
than the type of a function declaration). We previously didn't instantiate<br>
these at all! This also covers the pathological case where the only mention of<br>
a parameter pack is within the exception specification; this gives us a second<br>
way (other than alias templates) to reach the horrible state where a type<br>
contains an unexpanded pack, but its canonical type does not.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h<br>
    cfe/trunk/include/clang/AST/Expr.h<br>
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
    cfe/trunk/include/clang/AST/Type.h<br>
    cfe/trunk/include/clang/Sema/Sema.h<br>
    cfe/trunk/lib/AST/Type.cpp<br>
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
    cfe/trunk/lib/Sema/SemaExceptionSpec.cpp<br>
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp<br>
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
    cfe/trunk/lib/Sema/SemaType.cpp<br>
    cfe/trunk/lib/Sema/TreeTransform.h<br>
    cfe/trunk/test/CXX/except/except.spec/p1.cpp<br>
    cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp<br>
    cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp<br>
<br></div></div>...<div><div class="h5"><br>
Modified: cfe/trunk/lib/AST/Type.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/Type.cpp (original)<br>
+++ cfe/trunk/lib/AST/Type.cpp Wed Sep 17 18:57:05 2014<br>
@@ -1623,9 +1623,9 @@ FunctionProtoType::FunctionProtoType(Qua<br>
     QualType *exnSlot = argSlot + NumParams;<br>
     unsigned I = 0;<br>
     for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) {<br>
-      if (ExceptionType->isDependentType())<br>
-        setDependent();<br>
-      else if (ExceptionType->isInstantiationDependentType())<br>
+      // Note that a dependent exception specification does *not* make<br>
+      // a type dependent; it's not even part of the C++ type system.<br>
+      if (ExceptionType->isInstantiationDependentType())<br>
         setInstantiationDependent();<br>
<br>
       if (ExceptionType->containsUnexpandedParameterPack())<br>
@@ -1639,11 +1639,12 @@ FunctionProtoType::FunctionProtoType(Qua<br>
     *noexSlot = epi.ExceptionSpec.NoexceptExpr;<br>
<br>
     if (epi.ExceptionSpec.NoexceptExpr) {<br>
-      if (epi.ExceptionSpec.NoexceptExpr->isValueDependent()<br>
-          || epi.ExceptionSpec.NoexceptExpr->isTypeDependent())<br>
-        setDependent();<br>
-      else if (epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())<br>
+      if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() ||<br>
+          epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())<br>
         setInstantiationDependent();<br>
+<br>
+      if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack())<br>
+        setContainsUnexpandedParameterPack();<br>
     }<br>
   } else if (getExceptionSpecType() == EST_Uninstantiated) {<br>
     // Store the function decl from which we will resolve our<br>
@@ -1669,6 +1670,19 @@ FunctionProtoType::FunctionProtoType(Qua<br>
   }<br>
 }<br>
<br>
+bool FunctionProtoType::hasDependentExceptionSpec() const {<br>
+  if (Expr *NE = getNoexceptExpr())<br>
+    return NE->isValueDependent();<br>
+  for (unsigned I = 0, N = getNumExceptions(); I != N; ++I)<br></div></div></blockquote><div><br></div><div>This crashes on test/CXX/except/except.spec/template.cpp in certain build configurations. I suspect, the reason is the complicated relation between getNumExceptions/getExceptionType and exception_begin/exception_end:</div><div><br></div><font face="courier new, monospace">  exception_iterator exception_end() const {</font></div><div class="gmail_quote"><font face="courier new, monospace">    if (getExceptionSpecType() != EST_Dynamic)</font></div><div class="gmail_quote"><font face="courier new, monospace">      return exception_begin();</font></div><div class="gmail_quote"><font face="courier new, monospace">    return exception_begin() + NumExceptions;</font></div><div class="gmail_quote"><font face="courier new, monospace">  }</font></div><div class="gmail_quote"><font face="courier new, monospace">...<br>  unsigned getNumExceptions() const { return NumExceptions; }<br>  QualType getExceptionType(unsigned i) const {<br>    assert(i < NumExceptions && "Invalid exception number!");<br>    return exception_begin()[i];<br>  }</font><div><br></div><div>I wonder why the two ways to access exceptions are different. It looks like a bug.</div><div><br></div><div>Actually, I don't think we need getNumExceptions/getExceptionType, since there is ArrayRef<QualType> exceptions();.</div></div></div></div></blockquote><div><br></div><div>I've changed the code to use exceptions() instead of getNumExceptions/getExceptionType in r218053. All tests pass and the crash in my setup disappeared, so I assume that this is the right thing to do ;)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class="">
+    // A pack expansion with a non-dependent pattern is still dependent,<br>
+    // because we don't know whether the pattern is in the exception spec<br>
+    // or not (that depends on whether the pack has 0 expansions).<br>
+    if (getExceptionType(I)->isDependentType() ||<br>
+        getExceptionType(I)->getAs<PackExpansionType>())<br>
+      return true;<br>
+  return false;<br>
+}<br>
+<br>
 FunctionProtoType::NoexceptResult<br>
 FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const {<br>
   ExceptionSpecificationType est = getExceptionSpecType();<br></span>...</blockquote></div>
</div></div>
</blockquote></div><br>
</div></div>