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