<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">+ for (const auto &E :
T->exceptions())<br>
+ TRY_TO(TraverseType(E));<br>
<br>
You just need to enclose the body of this loop into braces.<br>
<pre class="moz-signature" cols="72">Best regards,
Alexey Bataev
=============
Software Engineer
Intel Compiler Team
Intel Corp. </pre>
18.09.2014 7:10, Reid Kleckner пишет:<br>
</div>
<blockquote
cite="mid:%3CCACs=ty+fpRvO-XL56RrWep4-OiSmd2aq5JNXc8EZvF2Niu+-8Q@mail.gmail.com%3E"
type="cite">
<div dir="ltr">
<div>This appears to not compile with MSVC 2013:</div>
llvm\tools\clang\include\clang/AST/RecursiveASTVisitor.h(2171) :
error C2059: syntax error : '}'<br>
<div><a moz-do-not-send="true"
href="http://build.chromium.org/p/chromium.fyi/builders/Cr%20Win%20Clang/builds/395/steps/runhooks/logs/stdio">http://build.chromium.org/p/chromium.fyi/builders/Cr%20Win%20Clang/builds/395/steps/runhooks/logs/stdio</a><br>
</div>
<div><br>
</div>
<div>I believe it is trying to say that TRY_TO doesn't work
inside of range-based for loops due to some insanity. This is
a known issue when updating RAV. =/</div>
</div>
<div class="gmail_extra"><br>
<div class="gmail_quote">On Wed, Sep 17, 2014 at 4:57 PM,
Richard Smith <span dir="ltr"><<a moz-do-not-send="true"
href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">Author:
rsmith<br>
Date: Wed Sep 17 18:57:05 2014<br>
New Revision: 217995<br>
<br>
URL: <a moz-do-not-send="true"
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>
Modified:
cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
(original)<br>
+++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
Wed Sep 17 18:57:05 2014<br>
@@ -876,6 +876,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, {<br>
for (const auto &E : T->exceptions()) {<br>
TRY_TO(TraverseType(E));<br>
}<br>
+<br>
+ if (Expr *NE = T->getNoexceptExpr())<br>
+ TRY_TO(TraverseStmt(NE));<br>
})<br>
<br>
DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})<br>
@@ -1084,6 +1087,9 @@
DEF_TRAVERSE_TYPELOC(FunctionProtoType,<br>
for (const auto &E : T->exceptions()) {<br>
TRY_TO(TraverseType(E));<br>
}<br>
+<br>
+ if (Expr *NE = T->getNoexceptExpr())<br>
+ TRY_TO(TraverseStmt(NE));<br>
})<br>
<br>
DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})<br>
@@ -2123,21 +2129,28 @@ bool
RecursiveASTVisitor<Derived>::Trave<br>
TRY_TO(TraverseLambdaCapture(S, C));<br>
}<br>
<br>
- if (S->hasExplicitParameters() ||
S->hasExplicitResultType()) {<br>
- TypeLoc TL =
S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();<br>
- if (S->hasExplicitParameters() &&
S->hasExplicitResultType()) {<br>
- // Visit the whole type.<br>
- TRY_TO(TraverseTypeLoc(TL));<br>
- } else if (FunctionProtoTypeLoc Proto =
TL.getAs<FunctionProtoTypeLoc>()) {<br>
- if (S->hasExplicitParameters()) {<br>
- // Visit parameters.<br>
- for (unsigned I = 0, N = Proto.getNumParams(); I !=
N; ++I) {<br>
- TRY_TO(TraverseDecl(Proto.getParam(I)));<br>
- }<br>
- } else {<br>
- TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));<br>
+ TypeLoc TL =
S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();<br>
+ FunctionProtoTypeLoc Proto =
TL.castAs<FunctionProtoTypeLoc>();<br>
+<br>
+ if (S->hasExplicitParameters() &&
S->hasExplicitResultType()) {<br>
+ // Visit the whole type.<br>
+ TRY_TO(TraverseTypeLoc(TL));<br>
+ } else {<br>
+ if (S->hasExplicitParameters()) {<br>
+ // Visit parameters.<br>
+ for (unsigned I = 0, N = Proto.getNumParams(); I !=
N; ++I) {<br>
+ TRY_TO(TraverseDecl(Proto.getParam(I)));<br>
}<br>
+ } else if (S->hasExplicitResultType()) {<br>
+ TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));<br>
}<br>
+<br>
+ auto *T = Proto.getTypePtr();<br>
+ for (const auto &E : T->exceptions())<br>
+ TRY_TO(TraverseType(E));<br>
+<br>
+ if (Expr *NE = T->getNoexceptExpr())<br>
+ TRY_TO(TraverseStmt(NE));<br>
}<br>
<br>
TRY_TO(TraverseLambdaBody(S));<br>
<br>
Modified: cfe/trunk/include/clang/AST/Expr.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/Expr.h (original)<br>
+++ cfe/trunk/include/clang/AST/Expr.h Wed Sep 17 18:57:05
2014<br>
@@ -2673,20 +2673,23 @@ private:<br>
}<br>
<br>
protected:<br>
- CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,<br>
- const CastKind kind, Expr *op, unsigned
BasePathSize) :<br>
- Expr(SC, ty, VK, OK_Ordinary,<br>
- // Cast expressions are type-dependent if the type
is<br>
- // dependent (C++ [temp.dep.expr]p3).<br>
- ty->isDependentType(),<br>
- // Cast expressions are value-dependent if the
type is<br>
- // dependent or if the subexpression is
value-dependent.<br>
- ty->isDependentType() || (op &&
op->isValueDependent()),<br>
- (ty->isInstantiationDependentType() ||<br>
- (op &&
op->isInstantiationDependent())),<br>
- (ty->containsUnexpandedParameterPack() ||<br>
- (op &&
op->containsUnexpandedParameterPack()))),<br>
- Op(op) {<br>
+ CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
const CastKind kind,<br>
+ Expr *op, unsigned BasePathSize)<br>
+ : Expr(SC, ty, VK, OK_Ordinary,<br>
+ // Cast expressions are type-dependent if the
type is<br>
+ // dependent (C++ [temp.dep.expr]p3).<br>
+ ty->isDependentType(),<br>
+ // Cast expressions are value-dependent if the
type is<br>
+ // dependent or if the subexpression is
value-dependent.<br>
+ ty->isDependentType() || (op &&
op->isValueDependent()),<br>
+ (ty->isInstantiationDependentType() ||<br>
+ (op &&
op->isInstantiationDependent())),<br>
+ // An implicit cast expression doesn't
(lexically) contain an<br>
+ // unexpanded pack, even if its target type
does.<br>
+ ((SC != ImplicitCastExprClass &&<br>
+ ty->containsUnexpandedParameterPack()) ||<br>
+ (op &&
op->containsUnexpandedParameterPack()))),<br>
+ Op(op) {<br>
assert(kind != CK_Invalid && "creating cast
with invalid cast kind");<br>
CastExprBits.Kind = kind;<br>
setBasePathSize(BasePathSize);<br>
<br>
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
(original)<br>
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed
Sep 17 18:57:05 2014<br>
@@ -941,6 +941,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, {<br>
for (const auto &E : T->exceptions()) {<br>
TRY_TO(TraverseType(E));<br>
}<br>
+<br>
+ if (Expr *NE = T->getNoexceptExpr())<br>
+ TRY_TO(TraverseStmt(NE));<br>
})<br>
<br>
DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})<br>
@@ -1149,6 +1152,9 @@
DEF_TRAVERSE_TYPELOC(FunctionProtoType,<br>
for (const auto &E : T->exceptions()) {<br>
TRY_TO(TraverseType(E));<br>
}<br>
+<br>
+ if (Expr *NE = T->getNoexceptExpr())<br>
+ TRY_TO(TraverseStmt(NE));<br>
})<br>
<br>
DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})<br>
@@ -2145,21 +2151,28 @@ bool
RecursiveASTVisitor<Derived>::Trave<br>
TRY_TO(TraverseLambdaCapture(S, C));<br>
}<br>
<br>
- if (S->hasExplicitParameters() ||
S->hasExplicitResultType()) {<br>
- TypeLoc TL =
S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();<br>
- if (S->hasExplicitParameters() &&
S->hasExplicitResultType()) {<br>
- // Visit the whole type.<br>
- TRY_TO(TraverseTypeLoc(TL));<br>
- } else if (FunctionProtoTypeLoc Proto =
TL.getAs<FunctionProtoTypeLoc>()) {<br>
- if (S->hasExplicitParameters()) {<br>
- // Visit parameters.<br>
- for (unsigned I = 0, N = Proto.getNumParams(); I !=
N; ++I) {<br>
- TRY_TO(TraverseDecl(Proto.getParam(I)));<br>
- }<br>
- } else {<br>
- TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));<br>
+ TypeLoc TL =
S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();<br>
+ FunctionProtoTypeLoc Proto =
TL.castAs<FunctionProtoTypeLoc>();<br>
+<br>
+ if (S->hasExplicitParameters() &&
S->hasExplicitResultType()) {<br>
+ // Visit the whole type.<br>
+ TRY_TO(TraverseTypeLoc(TL));<br>
+ } else {<br>
+ if (S->hasExplicitParameters()) {<br>
+ // Visit parameters.<br>
+ for (unsigned I = 0, N = Proto.getNumParams(); I !=
N; ++I) {<br>
+ TRY_TO(TraverseDecl(Proto.getParam(I)));<br>
}<br>
+ } else if (S->hasExplicitResultType()) {<br>
+ TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));<br>
}<br>
+<br>
+ auto *T = Proto.getTypePtr();<br>
+ for (const auto &E : T->exceptions())<br>
+ TRY_TO(TraverseType(E));<br>
+<br>
+ if (Expr *NE = T->getNoexceptExpr())<br>
+ TRY_TO(TraverseStmt(NE));<br>
}<br>
<br>
TRY_TO(TraverseLambdaBody(S));<br>
<br>
Modified: cfe/trunk/include/clang/AST/Type.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/Type.h (original)<br>
+++ cfe/trunk/include/clang/AST/Type.h Wed Sep 17 18:57:05
2014<br>
@@ -3012,6 +3012,8 @@ public:<br>
bool hasNoexceptExceptionSpec() const {<br>
return isNoexceptExceptionSpec(getExceptionSpecType());<br>
}<br>
+ /// \brief Return whether this function has a dependent
exception spec.<br>
+ bool hasDependentExceptionSpec() const;<br>
/// \brief Result type of getNoexceptSpec().<br>
enum NoexceptResult {<br>
NR_NoNoexcept, ///< There is no noexcept specifier.<br>
@@ -5247,8 +5249,8 @@ template <typename T> const T
*Type::cas<br>
ArrayType_cannot_be_used_with_getAs<T> at;<br>
(void) at;<br>
<br>
- assert(isa<T>(CanonicalType));<br>
if (const T *ty = dyn_cast<T>(this)) return ty;<br>
+ assert(isa<T>(CanonicalType));<br>
return cast<T>(getUnqualifiedDesugaredType());<br>
}<br>
<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Sep 17 18:57:05
2014<br>
@@ -4025,7 +4025,8 @@ public:<br>
<br>
/// \brief Check the given exception-specification and
update the<br>
/// exception specification information with the results.<br>
- void
checkExceptionSpecification(ExceptionSpecificationType EST,<br>
+ void checkExceptionSpecification(bool IsTopLevel,<br>
+
ExceptionSpecificationType EST,<br>
ArrayRef<ParsedType> DynamicExceptions,<br>
ArrayRef<SourceRange> DynamicExceptionRanges,<br>
Expr *NoexceptExpr,<br>
@@ -6652,6 +6653,8 @@ public:<br>
DeclarationName
Entity,<br>
CXXRecordDecl
*ThisContext,<br>
unsigned
ThisTypeQuals);<br>
+ void SubstExceptionSpec(FunctionDecl *New, const
FunctionProtoType *Proto,<br>
+ const
MultiLevelTemplateArgumentList &Args);<br>
ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,<br>
const
MultiLevelTemplateArgumentList &TemplateArgs,<br>
int indexAdjustment,<br>
<br>
Modified: cfe/trunk/lib/AST/Type.cpp<br>
URL: <a moz-do-not-send="true"
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>
+ // 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>
<br>
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Sep 17 18:57:05
2014<br>
@@ -13051,13 +13051,12 @@ bool
Sema::checkThisInStaticMemberFuncti<br>
return false;<br>
}<br>
<br>
-void<br>
-Sema::checkExceptionSpecification(ExceptionSpecificationType
EST,<br>
-
ArrayRef<ParsedType> DynamicExceptions,<br>
-
ArrayRef<SourceRange> DynamicExceptionRanges,<br>
- Expr *NoexceptExpr,<br>
-
SmallVectorImpl<QualType> &Exceptions,<br>
-
FunctionProtoType::ExceptionSpecInfo &ESI) {<br>
+void Sema::checkExceptionSpecification(<br>
+ bool IsTopLevel, ExceptionSpecificationType EST,<br>
+ ArrayRef<ParsedType> DynamicExceptions,<br>
+ ArrayRef<SourceRange> DynamicExceptionRanges,
Expr *NoexceptExpr,<br>
+ SmallVectorImpl<QualType> &Exceptions,<br>
+ FunctionProtoType::ExceptionSpecInfo &ESI) {<br>
Exceptions.clear();<br>
ESI.Type = EST;<br>
if (EST == EST_Dynamic) {<br>
@@ -13066,13 +13065,15 @@
Sema::checkExceptionSpecification(Except<br>
// FIXME: Preserve type source info.<br>
QualType ET =
GetTypeFromParser(DynamicExceptions[ei]);<br>
<br>
- SmallVector<UnexpandedParameterPack, 2>
Unexpanded;<br>
- collectUnexpandedParameterPacks(ET, Unexpanded);<br>
- if (!Unexpanded.empty()) {<br>
-
DiagnoseUnexpandedParameterPacks(DynamicExceptionRanges[ei].getBegin(),<br>
-
UPPC_ExceptionType,<br>
- Unexpanded);<br>
- continue;<br>
+ if (IsTopLevel) {<br>
+ SmallVector<UnexpandedParameterPack, 2>
Unexpanded;<br>
+ collectUnexpandedParameterPacks(ET, Unexpanded);<br>
+ if (!Unexpanded.empty()) {<br>
+ DiagnoseUnexpandedParameterPacks(<br>
+ DynamicExceptionRanges[ei].getBegin(),
UPPC_ExceptionType,<br>
+ Unexpanded);<br>
+ continue;<br>
+ }<br>
}<br>
<br>
// Check that the type is valid for an exception
spec, and<br>
@@ -13091,7 +13092,8 @@
Sema::checkExceptionSpecification(Except<br>
NoexceptExpr->getType()->getCanonicalTypeUnqualified()
==<br>
Context.BoolTy) &&<br>
"Parser should have made sure that the
expression is boolean");<br>
- if (NoexceptExpr &&
DiagnoseUnexpandedParameterPack(NoexceptExpr)) {<br>
+ if (IsTopLevel && NoexceptExpr &&<br>
+ DiagnoseUnexpandedParameterPack(NoexceptExpr)) {<br>
ESI.Type = EST_BasicNoexcept;<br>
return;<br>
}<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Wed Sep 17
18:57:05 2014<br>
@@ -720,10 +720,11 @@ static bool
CheckSpecForTypesEquivalent(<br>
/// assignment and override compatibility check. We do not
check the parameters<br>
/// of parameter function pointers recursively, as no sane
programmer would<br>
/// even be able to write such a function type.<br>
-bool Sema::CheckParamExceptionSpec(const PartialDiagnostic
& NoteID,<br>
- const FunctionProtoType *Target, SourceLocation
TargetLoc,<br>
- const FunctionProtoType *Source, SourceLocation
SourceLoc)<br>
-{<br>
+bool Sema::CheckParamExceptionSpec(const PartialDiagnostic
&NoteID,<br>
+ const FunctionProtoType
*Target,<br>
+ SourceLocation
TargetLoc,<br>
+ const FunctionProtoType
*Source,<br>
+ SourceLocation
SourceLoc) {<br>
if (CheckSpecForTypesEquivalent(<br>
*this,
PDiag(diag::err_deep_exception_specs_differ) << 0,
PDiag(),<br>
Target->getReturnType(), TargetLoc,
Source->getReturnType(),<br>
@@ -744,23 +745,30 @@ bool
Sema::CheckParamExceptionSpec(const<br>
return false;<br>
}<br>
<br>
-bool Sema::CheckExceptionSpecCompatibility(Expr *From,
QualType ToType)<br>
-{<br>
+bool Sema::CheckExceptionSpecCompatibility(Expr *From,
QualType ToType) {<br>
// First we check for applicability.<br>
// Target type must be a function, function pointer or
function reference.<br>
const FunctionProtoType *ToFunc =
GetUnderlyingFunction(ToType);<br>
- if (!ToFunc)<br>
+ if (!ToFunc || ToFunc->hasDependentExceptionSpec())<br>
return false;<br>
<br>
// SourceType must be a function or function pointer.<br>
const FunctionProtoType *FromFunc =
GetUnderlyingFunction(From->getType());<br>
- if (!FromFunc)<br>
+ if (!FromFunc ||
FromFunc->hasDependentExceptionSpec())<br>
return false;<br>
<br>
// Now we've got the correct types on both sides, check
their compatibility.<br>
// This means that the source of the conversion can only
throw a subset of<br>
// the exceptions of the target, and any exception specs
on arguments or<br>
// return types must be equivalent.<br>
+ //<br>
+ // FIXME: If there is a nested dependent exception
specification, we should<br>
+ // not be checking it here. This is fine:<br>
+ // template<typename T> void f() {<br>
+ // void (*p)(void (*) throw(T));<br>
+ // void (*q)(void (*) throw(int)) = p;<br>
+ // }<br>
+ // ... because it might be instantiated with T=int.<br>
return
CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs),<br>
PDiag(), ToFunc,<br>
From->getSourceRange().getBegin(),<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
(original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed Sep
17 18:57:05 2014<br>
@@ -788,12 +788,14 @@ namespace {<br>
/// pack.<br>
ExprResult
TransformFunctionParmPackExpr(FunctionParmPackExpr *E);<br>
<br>
- QualType TransformFunctionProtoType(TypeLocBuilder
&TLB,<br>
-
FunctionProtoTypeLoc TL);<br>
+ // Pull in the base class overload; it just forwards to
our function.<br>
+ using inherited::TransformFunctionProtoType;<br>
+ template<typename Fn><br>
QualType TransformFunctionProtoType(TypeLocBuilder
&TLB,<br>
FunctionProtoTypeLoc TL,<br>
CXXRecordDecl
*ThisContext,<br>
- unsigned
ThisTypeQuals);<br>
+ unsigned
ThisTypeQuals,<br>
+ Fn
TransformExceptionSpec);<br>
<br>
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl
*OldParm,<br>
int
indexAdjustment,<br>
@@ -1307,21 +1309,16 @@ ExprResult
TemplateInstantiator::Transfo<br>
E->getParam());<br>
}<br>
<br>
-QualType
TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder
&TLB,<br>
-
FunctionProtoTypeLoc TL) {<br>
- // We need a local instantiation scope for this function
prototype.<br>
- LocalInstantiationScope Scope(SemaRef,
/*CombineWithOuterScope=*/true);<br>
- return inherited::TransformFunctionProtoType(TLB, TL);<br>
-}<br>
-<br>
+template<typename Fn><br>
QualType
TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder
&TLB,<br>
FunctionProtoTypeLoc TL,<br>
CXXRecordDecl
*ThisContext,<br>
- unsigned ThisTypeQuals) {<br>
+ unsigned ThisTypeQuals,<br>
+ Fn TransformExceptionSpec)
{<br>
// We need a local instantiation scope for this function
prototype.<br>
LocalInstantiationScope Scope(SemaRef,
/*CombineWithOuterScope=*/true);<br>
- return inherited::TransformFunctionProtoType(TLB, TL,
ThisContext,<br>
-
ThisTypeQuals);<br>
+ return inherited::TransformFunctionProtoType(<br>
+ TLB, TL, ThisContext, ThisTypeQuals,
TransformExceptionSpec);<br>
}<br>
<br>
ParmVarDecl *<br>
@@ -1556,7 +1553,8 @@ static bool
NeedsInstantiationAsFunction<br>
<br>
/// A form of SubstType intended specifically for
instantiating the<br>
/// type of a FunctionDecl. Its purpose is solely to force
the<br>
-/// instantiation of default-argument expressions.<br>
+/// instantiation of default-argument expressions and to
avoid<br>
+/// instantiating an exception-specification.<br>
TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo
*T,<br>
const
MultiLevelTemplateArgumentList &Args,<br>
SourceLocation Loc,<br>
@@ -1579,9 +1577,17 @@ TypeSourceInfo
*Sema::SubstFunctionDeclT<br>
<br>
QualType Result;<br>
<br>
+ // FIXME: What if the function type is parenthesized?<br>
if (FunctionProtoTypeLoc Proto =
TL.getAs<FunctionProtoTypeLoc>()) {<br>
- Result = Instantiator.TransformFunctionProtoType(TLB,
Proto, ThisContext,<br>
-
ThisTypeQuals);<br>
+ // Instantiate the type, other than its exception
specification. The<br>
+ // exception specification is instantiated in
InitFunctionInstantiation<br>
+ // once we've built the FunctionDecl.<br>
+ // FIXME: Set the exception specification to
EST_Uninstantiated here,<br>
+ // instead of rebuilding the function type again later.<br>
+ Result = Instantiator.TransformFunctionProtoType(<br>
+ TLB, Proto, ThisContext, ThisTypeQuals,<br>
+ [](FunctionProtoType::ExceptionSpecInfo &ESI,<br>
+ bool &Changed) { return false; });<br>
} else {<br>
Result = Instantiator.TransformType(TLB, TL);<br>
}<br>
@@ -1591,6 +1597,26 @@ TypeSourceInfo
*Sema::SubstFunctionDeclT<br>
return TLB.getTypeSourceInfo(Context, Result);<br>
}<br>
<br>
+void Sema::SubstExceptionSpec(FunctionDecl *New, const
FunctionProtoType *Proto,<br>
+ const
MultiLevelTemplateArgumentList &Args) {<br>
+ FunctionProtoType::ExceptionSpecInfo ESI =<br>
+ Proto->getExtProtoInfo().ExceptionSpec;<br>
+ assert(ESI.Type != EST_Uninstantiated);<br>
+<br>
+ TemplateInstantiator Instantiator(*this, Args,
New->getLocation(),<br>
+ New->getDeclName());<br>
+<br>
+ SmallVector<QualType, 4> ExceptionStorage;<br>
+ bool Changed = false;<br>
+ if (Instantiator.TransformExceptionSpec(<br>
+
New->getTypeSourceInfo()->getTypeLoc().getLocEnd(),
ESI,<br>
+ ExceptionStorage, Changed))<br>
+ // On error, recover by dropping the exception
specification.<br>
+ ESI.Type = EST_None;<br>
+<br>
+ UpdateExceptionSpec(New, ESI);<br>
+}<br>
+<br>
ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,<br>
const
MultiLevelTemplateArgumentList &TemplateArgs,<br>
int indexAdjustment,<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
(original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed
Sep 17 18:57:05 2014<br>
@@ -2988,7 +2988,7 @@
TemplateDeclInstantiator::SubstFunctionT<br>
/// Introduce the instantiated function parameters into the
local<br>
/// instantiation scope, and set the parameter names to
those used<br>
/// in the template.<br>
-static void addInstantiatedParametersToScope(Sema &S,
FunctionDecl *Function,<br>
+static bool addInstantiatedParametersToScope(Sema &S,
FunctionDecl *Function,<br>
const
FunctionDecl *PatternDecl,<br>
LocalInstantiationScope &Scope,<br>
const
MultiLevelTemplateArgumentList &TemplateArgs) {<br>
@@ -2999,15 +2999,22 @@ static void
addInstantiatedParametersToS<br>
// Simple case: not a parameter pack.<br>
assert(FParamIdx < Function->getNumParams());<br>
ParmVarDecl *FunctionParam =
Function->getParamDecl(FParamIdx);<br>
+
FunctionParam->setDeclName(PatternParam->getDeclName());<br>
// If the parameter's type is not dependent, update
it to match the type<br>
// in the pattern. They can differ in top-level
cv-qualifiers, and we want<br>
// the pattern's type here. If the type is dependent,
they can't differ,<br>
- // per core issue 1668.<br>
+ // per core issue 1668. Substitute into the type from
the pattern, in case<br>
+ // it's instantiation-dependent.<br>
// FIXME: Updating the type to work around this is at
best fragile.<br>
- if (!PatternDecl->getType()->isDependentType())<br>
-
FunctionParam->setType(PatternParam->getType());<br>
+ if (!PatternDecl->getType()->isDependentType())
{<br>
+ QualType T =
S.SubstType(PatternParam->getType(), TemplateArgs,<br>
+
FunctionParam->getLocation(),<br>
+
FunctionParam->getDeclName());<br>
+ if (T.isNull())<br>
+ return true;<br>
+ FunctionParam->setType(T);<br>
+ }<br>
<br>
-
FunctionParam->setDeclName(PatternParam->getDeclName());<br>
Scope.InstantiatedLocal(PatternParam, FunctionParam);<br>
++FParamIdx;<br>
continue;<br>
@@ -3019,136 +3026,27 @@ static void
addInstantiatedParametersToS<br>
=
S.getNumArgumentsInExpansion(PatternParam->getType(),
TemplateArgs);<br>
assert(NumArgumentsInExpansion &&<br>
"should only be called when all template
arguments are known");<br>
+ QualType PatternType =<br>
+
PatternParam->getType()->castAs<PackExpansionType>()->getPattern();<br>
for (unsigned Arg = 0; Arg <
*NumArgumentsInExpansion; ++Arg) {<br>
ParmVarDecl *FunctionParam =
Function->getParamDecl(FParamIdx);<br>
- if (!PatternDecl->getType()->isDependentType())<br>
-
FunctionParam->setType(PatternParam->getType());<br>
-<br>
FunctionParam->setDeclName(PatternParam->getDeclName());<br>
- Scope.InstantiatedLocalPackArg(PatternParam,
FunctionParam);<br>
- ++FParamIdx;<br>
- }<br>
- }<br>
-}<br>
-<br>
-static void InstantiateExceptionSpec(Sema &SemaRef,
FunctionDecl *New,<br>
- const
FunctionProtoType *Proto,<br>
- const
MultiLevelTemplateArgumentList &TemplateArgs) {<br>
- assert(Proto->getExceptionSpecType() !=
EST_Uninstantiated);<br>
-<br>
- // C++11 [expr.prim.general]p3:<br>
- // If a declaration declares a member function or
member function<br>
- // template of a class X, the expression this is a
prvalue of type<br>
- // "pointer to cv-qualifier-seq X" between the optional
cv-qualifer-seq<br>
- // and the end of the function-definition,
member-declarator, or<br>
- // declarator.<br>
- CXXRecordDecl *ThisContext = nullptr;<br>
- unsigned ThisTypeQuals = 0;<br>
- if (CXXMethodDecl *Method =
dyn_cast<CXXMethodDecl>(New)) {<br>
- ThisContext = Method->getParent();<br>
- ThisTypeQuals = Method->getTypeQualifiers();<br>
- }<br>
- Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext,
ThisTypeQuals,<br>
-
SemaRef.getLangOpts().CPlusPlus11);<br>
-<br>
- // The function has an exception specification or a
"noreturn"<br>
- // attribute. Substitute into each of the exception
types.<br>
- SmallVector<QualType, 4> Exceptions;<br>
- for (unsigned I = 0, N = Proto->getNumExceptions(); I
!= N; ++I) {<br>
- // FIXME: Poor location information!<br>
- if (const PackExpansionType *PackExpansion<br>
- =
Proto->getExceptionType(I)->getAs<PackExpansionType>())
{<br>
- // We have a pack expansion. Instantiate it.<br>
- SmallVector<UnexpandedParameterPack, 2>
Unexpanded;<br>
-
SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),<br>
- Unexpanded);<br>
- assert(!Unexpanded.empty() &&<br>
- "Pack expansion without parameter packs?");<br>
-<br>
- bool Expand = false;<br>
- bool RetainExpansion = false;<br>
- Optional<unsigned> NumExpansions =
PackExpansion->getNumExpansions();<br>
- if
(SemaRef.CheckParameterPacksForExpansion(New->getLocation(),<br>
-
SourceRange(),<br>
-
Unexpanded,<br>
-
TemplateArgs,<br>
- Expand,<br>
-
RetainExpansion,<br>
-
NumExpansions))<br>
- break;<br>
-<br>
- if (!Expand) {<br>
- // We can't expand this pack expansion into
separate arguments yet;<br>
- // just substitute into the pattern and create a
new pack expansion<br>
- // type.<br>
- Sema::ArgumentPackSubstitutionIndexRAII
SubstIndex(SemaRef, -1);<br>
- QualType T =
SemaRef.SubstType(PackExpansion->getPattern(),<br>
- TemplateArgs,<br>
- New->getLocation(),
New->getDeclName());<br>
+ if (!PatternDecl->getType()->isDependentType())
{<br>
+ Sema::ArgumentPackSubstitutionIndexRAII
SubstIndex(S, Arg);<br>
+ QualType T = S.SubstType(PatternType, TemplateArgs,<br>
+
FunctionParam->getLocation(),<br>
+
FunctionParam->getDeclName());<br>
if (T.isNull())<br>
- break;<br>
-<br>
- T = SemaRef.Context.getPackExpansionType(T,
NumExpansions);<br>
- Exceptions.push_back(T);<br>
- continue;<br>
- }<br>
-<br>
- // Substitute into the pack expansion pattern for
each template<br>
- bool Invalid = false;<br>
- for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions;
++ArgIdx) {<br>
- Sema::ArgumentPackSubstitutionIndexRAII
SubstIndex(SemaRef, ArgIdx);<br>
-<br>
- QualType T =
SemaRef.SubstType(PackExpansion->getPattern(),<br>
- TemplateArgs,<br>
- New->getLocation(),
New->getDeclName());<br>
- if (T.isNull()) {<br>
- Invalid = true;<br>
- break;<br>
- }<br>
-<br>
- Exceptions.push_back(T);<br>
+ return true;<br>
+ FunctionParam->setType(T);<br>
}<br>
<br>
- if (Invalid)<br>
- break;<br>
-<br>
- continue;<br>
- }<br>
-<br>
- QualType T<br>
- = SemaRef.SubstType(Proto->getExceptionType(I),
TemplateArgs,<br>
- New->getLocation(),
New->getDeclName());<br>
- if (T.isNull() ||<br>
- SemaRef.CheckSpecifiedExceptionType(T,
New->getLocation()))<br>
- continue;<br>
-<br>
- Exceptions.push_back(T);<br>
- }<br>
- Expr *NoexceptExpr = nullptr;<br>
- if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr())
{<br>
- EnterExpressionEvaluationContext Unevaluated(SemaRef,<br>
-
Sema::ConstantEvaluated);<br>
- ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr,
TemplateArgs);<br>
- if (E.isUsable())<br>
- E = SemaRef.CheckBooleanCondition(E.get(),
E.get()->getLocStart());<br>
-<br>
- if (E.isUsable()) {<br>
- NoexceptExpr = E.get();<br>
- if (!NoexceptExpr->isTypeDependent() &&<br>
- !NoexceptExpr->isValueDependent())<br>
- NoexceptExpr<br>
- =
SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,<br>
- nullptr,
diag::err_noexcept_needs_constant_expression,<br>
- /*AllowFold*/ false).get();<br>
+ Scope.InstantiatedLocalPackArg(PatternParam,
FunctionParam);<br>
+ ++FParamIdx;<br>
}<br>
}<br>
<br>
- FunctionProtoType::ExceptionSpecInfo ESI;<br>
- ESI.Type = Proto->getExceptionSpecType();<br>
- ESI.Exceptions = Exceptions;<br>
- ESI.NoexceptExpr = NoexceptExpr;<br>
-<br>
- SemaRef.UpdateExceptionSpec(New, ESI);<br>
+ return false;<br>
}<br>
<br>
void Sema::InstantiateExceptionSpec(SourceLocation
PointOfInstantiation,<br>
@@ -3175,11 +3073,14 @@ void
Sema::InstantiateExceptionSpec(Sour<br>
getTemplateInstantiationArgs(Decl, nullptr,
/*RelativeToPrimary*/true);<br>
<br>
FunctionDecl *Template =
Proto->getExceptionSpecTemplate();<br>
- addInstantiatedParametersToScope(*this, Decl, Template,
Scope, TemplateArgs);<br>
+ if (addInstantiatedParametersToScope(*this, Decl,
Template, Scope,<br>
+ TemplateArgs)) {<br>
+ UpdateExceptionSpec(Decl, EST_None);<br>
+ return;<br>
+ }<br>
<br>
- ::InstantiateExceptionSpec(*this, Decl,<br>
-
Template->getType()->castAs<FunctionProtoType>(),<br>
- TemplateArgs);<br>
+ SubstExceptionSpec(Decl,
Template->getType()->castAs<FunctionProtoType>(),<br>
+ TemplateArgs);<br>
}<br>
<br>
/// \brief Initializes the common fields of an
instantiation function<br>
@@ -3248,7 +3149,7 @@
TemplateDeclInstantiator::InitFunctionIn<br>
New->setType(SemaRef.Context.getFunctionType(<br>
NewProto->getReturnType(),
NewProto->getParamTypes(), EPI));<br>
} else {<br>
- ::InstantiateExceptionSpec(SemaRef, New, Proto,
TemplateArgs);<br>
+ SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs);<br>
}<br>
}<br>
<br>
@@ -3438,8 +3339,9 @@ void
Sema::InstantiateFunctionDefinition<br>
MultiLevelTemplateArgumentList TemplateArgs =<br>
getTemplateInstantiationArgs(Function, nullptr,
false, PatternDecl);<br>
<br>
- addInstantiatedParametersToScope(*this, Function,
PatternDecl, Scope,<br>
- TemplateArgs);<br>
+ if (addInstantiatedParametersToScope(*this, Function,
PatternDecl, Scope,<br>
+ TemplateArgs))<br>
+ return;<br>
<br>
// If this is a constructor, instantiate the member
initializers.<br>
if (const CXXConstructorDecl *Ctor =<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaType.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaType.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Sep 17 18:57:05 2014<br>
@@ -2989,7 +2989,8 @@ static TypeSourceInfo
*GetFullTypeForDec<br>
NoexceptExpr = FTI.NoexceptExpr;<br>
}<br>
<br>
-
S.checkExceptionSpecification(FTI.getExceptionSpecType(),<br>
+
S.checkExceptionSpecification(D.isFunctionDeclarationContext(),<br>
+
FTI.getExceptionSpecType(),<br>
DynamicExceptions,<br>
DynamicExceptionRanges,<br>
NoexceptExpr,<br>
<br>
Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Sep 17 18:57:05
2014<br>
@@ -542,10 +542,17 @@ public:<br>
QualType Transform##CLASS##Type(TypeLocBuilder &TLB,
CLASS##TypeLoc T);<br>
#include "clang/AST/TypeLocNodes.def"<br>
<br>
+ template<typename Fn><br>
QualType TransformFunctionProtoType(TypeLocBuilder
&TLB,<br>
FunctionProtoTypeLoc
TL,<br>
CXXRecordDecl
*ThisContext,<br>
- unsigned
ThisTypeQuals);<br>
+ unsigned
ThisTypeQuals,<br>
+ Fn
TransformExceptionSpec);<br>
+<br>
+ bool TransformExceptionSpec(SourceLocation Loc,<br>
+
FunctionProtoType::ExceptionSpecInfo &ESI,<br>
+
SmallVectorImpl<QualType> &Exceptions,<br>
+ bool &Changed);<br>
<br>
StmtResult TransformSEHHandler(Stmt *Handler);<br>
<br>
@@ -4512,15 +4519,19 @@ template<typename Derived><br>
QualType<br>
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder
&TLB,<br>
FunctionProtoTypeLoc TL) {<br>
- return getDerived().TransformFunctionProtoType(TLB, TL,
nullptr, 0);<br>
+ SmallVector<QualType, 4> ExceptionStorage;<br>
+ return getDerived().TransformFunctionProtoType(<br>
+ TLB, TL, nullptr, 0,<br>
+ [&](FunctionProtoType::ExceptionSpecInfo
&ESI, bool &Changed) {<br>
+ return TransformExceptionSpec(TL.getBeginLoc(),
ESI, ExceptionStorage,<br>
+ Changed);<br>
+ });<br>
}<br>
<br>
-template<typename Derived><br>
-QualType<br>
-TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder
&TLB,<br>
-
FunctionProtoTypeLoc TL,<br>
-
CXXRecordDecl *ThisContext,<br>
- unsigned
ThisTypeQuals) {<br>
+template<typename Derived> template<typename
Fn><br>
+QualType
TreeTransform<Derived>::TransformFunctionProtoType(<br>
+ TypeLocBuilder &TLB, FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,<br>
+ unsigned ThisTypeQuals, Fn TransformExceptionSpec) {<br>
// Transform the parameters and return type.<br>
//<br>
// We are required to instantiate the params and return
type in source order.<br>
@@ -4565,15 +4576,21 @@
TreeTransform<Derived>::TransformFunctio<br>
return QualType();<br>
}<br>
<br>
- // FIXME: Need to transform the exception-specification
too.<br>
+ FunctionProtoType::ExtProtoInfo EPI =
T->getExtProtoInfo();<br>
+<br>
+ bool EPIChanged = false;<br>
+ if (TransformExceptionSpec(EPI.ExceptionSpec,
EPIChanged))<br>
+ return QualType();<br>
+<br>
+ // FIXME: Need to transform ConsumedParameters for
variadic template<br>
+ // expansion.<br>
<br>
QualType Result = TL.getType();<br>
if (getDerived().AlwaysRebuild() || ResultType !=
T->getReturnType() ||<br>
T->getNumParams() != ParamTypes.size() ||<br>
!std::equal(T->param_type_begin(),
T->param_type_end(),<br>
- ParamTypes.begin())) {<br>
- Result =
getDerived().RebuildFunctionProtoType(ResultType,
ParamTypes,<br>
-
T->getExtProtoInfo());<br>
+ ParamTypes.begin()) || EPIChanged) {<br>
+ Result =
getDerived().RebuildFunctionProtoType(ResultType,
ParamTypes, EPI);<br>
if (Result.isNull())<br>
return QualType();<br>
}<br>
@@ -4590,6 +4607,107 @@
TreeTransform<Derived>::TransformFunctio<br>
}<br>
<br>
template<typename Derived><br>
+bool TreeTransform<Derived>::TransformExceptionSpec(<br>
+ SourceLocation Loc,
FunctionProtoType::ExceptionSpecInfo &ESI,<br>
+ SmallVectorImpl<QualType> &Exceptions, bool
&Changed) {<br>
+ assert(ESI.Type != EST_Uninstantiated && ESI.Type
!= EST_Unevaluated);<br>
+<br>
+ // Instantiate a dynamic noexcept expression, if any.<br>
+ if (ESI.Type == EST_ComputedNoexcept) {<br>
+ EnterExpressionEvaluationContext Unevaluated(getSema(),<br>
+
Sema::ConstantEvaluated);<br>
+ ExprResult NoexceptExpr =
getDerived().TransformExpr(ESI.NoexceptExpr);<br>
+ if (NoexceptExpr.isInvalid())<br>
+ return true;<br>
+<br>
+ NoexceptExpr = getSema().CheckBooleanCondition(<br>
+ NoexceptExpr.get(),
NoexceptExpr.get()->getLocStart());<br>
+ if (NoexceptExpr.isInvalid())<br>
+ return true;<br>
+<br>
+ if (!NoexceptExpr.get()->isValueDependent()) {<br>
+ NoexceptExpr =
getSema().VerifyIntegerConstantExpression(<br>
+ NoexceptExpr.get(), nullptr,<br>
+ diag::err_noexcept_needs_constant_expression,<br>
+ /*AllowFold*/false);<br>
+ if (NoexceptExpr.isInvalid())<br>
+ return true;<br>
+ }<br>
+<br>
+ if (ESI.NoexceptExpr != NoexceptExpr.get())<br>
+ Changed = true;<br>
+ ESI.NoexceptExpr = NoexceptExpr.get();<br>
+ }<br>
+<br>
+ if (ESI.Type != EST_Dynamic)<br>
+ return false;<br>
+<br>
+ // Instantiate a dynamic exception specification's type.<br>
+ for (QualType T : ESI.Exceptions) {<br>
+ if (const PackExpansionType *PackExpansion =<br>
+ T->getAs<PackExpansionType>()) {<br>
+ Changed = true;<br>
+<br>
+ // We have a pack expansion. Instantiate it.<br>
+ SmallVector<UnexpandedParameterPack, 2>
Unexpanded;<br>
+
SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),<br>
+ Unexpanded);<br>
+ assert(!Unexpanded.empty() && "Pack expansion
without parameter packs?");<br>
+<br>
+ // Determine whether the set of unexpanded parameter
packs can and<br>
+ // should<br>
+ // be expanded.<br>
+ bool Expand = false;<br>
+ bool RetainExpansion = false;<br>
+ Optional<unsigned> NumExpansions =
PackExpansion->getNumExpansions();<br>
+ // FIXME: Track the location of the ellipsis (and
track source location<br>
+ // information for the types in the exception
specification in general).<br>
+ if (getDerived().TryExpandParameterPacks(<br>
+ Loc, SourceRange(), Unexpanded, Expand,<br>
+ RetainExpansion, NumExpansions))<br>
+ return true;<br>
+<br>
+ if (!Expand) {<br>
+ // We can't expand this pack expansion into
separate arguments yet;<br>
+ // just substitute into the pattern and create a
new pack expansion<br>
+ // type.<br>
+ Sema::ArgumentPackSubstitutionIndexRAII
SubstIndex(getSema(), -1);<br>
+ QualType U =
getDerived().TransformType(PackExpansion->getPattern());<br>
+ if (U.isNull())<br>
+ return true;<br>
+<br>
+ U = SemaRef.Context.getPackExpansionType(U,
NumExpansions);<br>
+ Exceptions.push_back(U);<br>
+ continue;<br>
+ }<br>
+<br>
+ // Substitute into the pack expansion pattern for
each slice of the<br>
+ // pack.<br>
+ for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions;
++ArgIdx) {<br>
+ Sema::ArgumentPackSubstitutionIndexRAII
SubstIndex(getSema(), ArgIdx);<br>
+<br>
+ QualType U =
getDerived().TransformType(PackExpansion->getPattern());<br>
+ if (U.isNull() ||
SemaRef.CheckSpecifiedExceptionType(U, Loc))<br>
+ return true;<br>
+<br>
+ Exceptions.push_back(U);<br>
+ }<br>
+ } else {<br>
+ QualType U = getDerived().TransformType(T);<br>
+ if (U.isNull() ||
SemaRef.CheckSpecifiedExceptionType(U, Loc))<br>
+ return true;<br>
+ if (T != U)<br>
+ Changed = true;<br>
+<br>
+ Exceptions.push_back(U);<br>
+ }<br>
+ }<br>
+<br>
+ ESI.Exceptions = Exceptions;<br>
+ return false;<br>
+}<br>
+<br>
+template<typename Derived><br>
QualType
TreeTransform<Derived>::TransformFunctionNoProtoType(<br>
TypeLocBuilder &TLB,<br>
FunctionNoProtoTypeLoc TL) {<br>
@@ -8895,9 +9013,13 @@
TreeTransform<Derived>::TransformLambdaE<br>
// transformed parameters.<br>
<br>
TypeLocBuilder NewCallOpTLBuilder;<br>
- QualType NewCallOpType =
TransformFunctionProtoType(NewCallOpTLBuilder,<br>
-
OldCallOpFPTL,<br>
-
nullptr, 0);<br>
+ SmallVector<QualType, 4> ExceptionStorage;<br>
+ QualType NewCallOpType = TransformFunctionProtoType(<br>
+ NewCallOpTLBuilder, OldCallOpFPTL, nullptr, 0,<br>
+ [&](FunctionProtoType::ExceptionSpecInfo
&ESI, bool &Changed) {<br>
+ return
TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,<br>
+ ExceptionStorage,
Changed);<br>
+ });<br>
NewCallOpTSI =
NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,<br>
NewCallOpType);<br>
}<br>
<br>
Modified: cfe/trunk/test/CXX/except/except.spec/p1.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p1.cpp?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p1.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/except/except.spec/p1.cpp (original)<br>
+++ cfe/trunk/test/CXX/except/except.spec/p1.cpp Wed Sep 17
18:57:05 2014<br>
@@ -77,5 +77,12 @@ namespace PR11084 {<br>
static int f() noexcept(1/X) { return 10; } //
expected-error{{argument to noexcept specifier must be a
constant expression}} expected-note{{division by zero}}<br>
};<br>
<br>
- void g() { A<0>::f(); } // expected-note{{in
instantiation of exception specification for 'f' requested
here}}<br>
+ template<int X> void f() {<br>
+ int (*p)() noexcept(1/X); // expected-error{{argument
to noexcept specifier must be a constant expression}}
expected-note{{division by zero}}<br>
+ };<br>
+<br>
+ void g() {<br>
+ A<0>::f(); // expected-note{{in instantiation of
exception specification for 'f'}}<br>
+ f<0>(); // expected-note{{in instantiation of
function template specialization}}<br>
+ }<br>
}<br>
<br>
Modified:
cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
---
cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
(original)<br>
+++
cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
Wed Sep 17 18:57:05 2014<br>
@@ -137,3 +137,37 @@ namespace PR12763 {<br>
};<br>
void X::g() {} // expected-note {{in instantiation of}}<br>
}<br>
+<br>
+namespace Variadic {<br>
+ template<bool B> void check() { static_assert(B,
""); }<br>
+ template<bool B, bool B2, bool ...Bs> void check()
{ static_assert(B, ""); check<B2, Bs...>(); }<br>
+<br>
+ template<typename ...T> void consume(T...);<br>
+<br>
+ template<typename ...T> void f(void (*...p)() throw
(T)) {<br>
+ void (*q[])() = { p... };<br>
+ consume((p(),0)...);<br>
+ }<br>
+ template<bool ...B> void g(void (*...p)() noexcept
(B)) {<br>
+ consume((p(),0)...);<br>
+ check<noexcept(p()) == B ...>();<br>
+ }<br>
+ template<typename ...T> void i() {<br>
+ consume([]() throw(T) {} ...);<br>
+ consume([]() noexcept(sizeof(T) == 4) {} ...);<br>
+ }<br>
+ template<bool ...B> void j() {<br>
+ consume([](void (*p)() noexcept(B)) {<br>
+ void (*q)() noexcept = p; // expected-error {{not
superset of source}}<br>
+ } ...);<br>
+ }<br>
+<br>
+ void z() {<br>
+ f<int, char, double>(nullptr, nullptr, nullptr);<br>
+ g<true, false, true>(nullptr, nullptr, nullptr);<br>
+ i<int, long, short>();<br>
+ j<true, true>();<br>
+ j<true, false>(); // expected-note {{in
instantiation of}}<br>
+ }<br>
+<br>
+}<br>
<br>
Modified:
cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp?rev=217995&r1=217994&r2=217995&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
---
cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp
(original)<br>
+++
cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp
Wed Sep 17 18:57:05 2014<br>
@@ -1,5 +1,7 @@<br>
-// RUN: %clang_cc1 -fsyntax-only -verify %s<br>
+// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -verify %s
-DERRORS<br>
+// RUN: %clang_cc1 -fexceptions -fcxx-exceptions
-emit-llvm-only %s<br>
<br>
+#ifdef ERRORS<br>
template<typename T> void f1(T*) throw(T); //
expected-error{{incomplete type 'Incomplete' is not allowed
in exception specification}}<br>
struct Incomplete; // expected-note{{forward}}<br>
<br>
@@ -7,3 +9,20 @@ void test_f1(Incomplete *incomplete_p, i<br>
f1(int_p);<br>
f1(incomplete_p); // expected-note{{instantiation of}}<br>
}<br>
+#endif<br>
+<br>
+template<typename T> void f(void (*p)() throw(T)) {<br>
+#ifdef ERRORS<br>
+ void (*q)() throw(char) = p; // expected-error {{target
exception spec}}<br>
+<br>
+ extern void (*p2)() throw(T);<br>
+ void (*q2)() throw(char) = p2; // expected-error {{target
exception spec}}<br>
+<br>
+ extern void (*p3)() throw(char);<br>
+ void (*q3)() throw(T) = p3; // expected-error {{target
exception spec}}<br>
+<br>
+ void (*q4)() throw(T) = p2; // ok<br>
+#endif<br>
+ p();<br>
+}<br>
+void g() { f<int>(0); } // expected-note
{{instantiation of}}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a moz-do-not-send="true"
href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a moz-do-not-send="true"
href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits"
target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote>
</div>
<br>
</div>
</blockquote>
<br>
</body>
</html>