<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>