diff options
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index ae72c5853ce..1804c006476 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2111,6 +2111,62 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, L->DeducedReturnType(FD, ResultType); } +/// Get a function type and produce the equivalent function type with the +/// specified exception specification. Type sugar that can be present on a +/// declaration of a function with an exception specification is permitted +/// and preserved. Other type sugar (for instance, typedefs) is not. +static QualType getFunctionTypeWithExceptionSpec( + ASTContext &Context, QualType Orig, + const FunctionProtoType::ExceptionSpecInfo &ESI) { + // Might have some parens. + if (auto *PT = dyn_cast<ParenType>(Orig)) + return Context.getParenType( + getFunctionTypeWithExceptionSpec(Context, PT->getInnerType(), ESI)); + + // Might have a calling-convention attribute. + if (auto *AT = dyn_cast<AttributedType>(Orig)) + return Context.getAttributedType( + AT->getAttrKind(), + getFunctionTypeWithExceptionSpec(Context, AT->getModifiedType(), ESI), + getFunctionTypeWithExceptionSpec(Context, AT->getEquivalentType(), + ESI)); + + // Anything else must be a function type. Rebuild it with the new exception + // specification. + const FunctionProtoType *Proto = cast<FunctionProtoType>(Orig); + return Context.getFunctionType( + Proto->getReturnType(), Proto->getParamTypes(), + Proto->getExtProtoInfo().withExceptionSpec(ESI)); +} + +void ASTContext::adjustExceptionSpec( + FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI, + bool AsWritten) { + // Update the type. + QualType Updated = + getFunctionTypeWithExceptionSpec(*this, FD->getType(), ESI); + FD->setType(Updated); + + if (!AsWritten) + return; + + // Update the type in the type source information too. + if (TypeSourceInfo *TSInfo = FD->getTypeSourceInfo()) { + // If the type and the type-as-written differ, we may need to update + // the type-as-written too. + if (TSInfo->getType() != FD->getType()) + Updated = getFunctionTypeWithExceptionSpec(*this, TSInfo->getType(), ESI); + + // FIXME: When we get proper type location information for exceptions, + // we'll also have to rebuild the TypeSourceInfo. For now, we just patch + // up the TypeSourceInfo; + assert(TypeLoc::getFullDataSizeForType(Updated) == + TypeLoc::getFullDataSizeForType(TSInfo->getType()) && + "TypeLoc size mismatch from updating exception specification"); + TSInfo->overrideType(Updated); + } +} + /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. QualType ASTContext::getComplexType(QualType T) const { |