//===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides Sema routines for C++ exception specification testing.
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
namespace clang {
static const FunctionProtoType *GetUnderlyingFunction(QualType T)
{
if (const PointerType *PtrTy = T->getAs<PointerType>())
T = PtrTy->getPointeeType();
else if (const ReferenceType *RefTy = T->getAs<ReferenceType>())
T = RefTy->getPointeeType();
else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
T = MPTy->getPointeeType();
return T->getAs<FunctionProtoType>();
}
/// CheckSpecifiedExceptionType - Check if the given type is valid in an
/// exception specification. Incomplete types, or pointers to incomplete types
/// other than void are not allowed.
bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
// This check (and the similar one below) deals with issue 437, that changes
// C++ 9.2p2 this way:
// Within the class member-specification, the class is regarded as complete
// within function bodies, default arguments, exception-specifications, and
// constructor ctor-initializers (including such things in nested classes).
if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
return false;
// C++ 15.4p2: A type denoted in an exception-specification shall not denote
// an incomplete type.
if (RequireCompleteType(Range.getBegin(), T,
diag::err_incomplete_in_exception_spec,
/*direct*/0, Range))
return true;
// C++ 15.4p2: A type denoted in an exception-specification shall not denote
// an incomplete type a pointer or reference to an incomplete type, other
// than (cv) void*.
int kind;
if (const PointerType* IT = T->getAs<PointerType>()) {
T = IT->getPointeeType();
kind = 1;
} else if (const ReferenceType* IT = T->getAs<ReferenceType>()) {
T = IT->getPointeeType();
kind = 2;
} else
return false;
// Again as before
if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
return false;
if (!T->isVoidType() &&
RequireCompleteType(Range.getBegin(), T,
diag::err_incomplete_in_exception_spec, kind, Range))
return true;
return false;
}
/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer
/// to member to a function with an exception specification. This means that
/// it is invalid to add another level of indirection.
bool Sema::CheckDistantExceptionSpec(QualType T) {
if (const PointerType *PT = T->getAs<PointerType>())
T = PT->getPointeeType();
else if (const MemberPointerType *PT = T->getAs<MemberPointerType>())
T = PT->getPointeeType();
else
return false;
const FunctionProtoType *FnT = T->getAs<FunctionProtoType>();
if (!FnT)
return false;
return FnT->hasExceptionSpec();
}
const FunctionProtoType *
Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
// FIXME: If FD is a special member, we should delay computing its exception
// specification until this point.
if (FPT->getExceptionSpecType() != EST_Uninstantiated)
return FPT;
FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl();
const FunctionProtoType *SourceFPT =
SourceDecl->getType()->castAs<FunctionProtoType>();
if (SourceFPT->getExceptionSpecType() != EST_Uninstantiated)
return SourceFPT;
// Instantiate the exception specification now.
InstantiateExceptionSpec(Loc, SourceDecl);
return SourceDecl->getType()->castAs<FunctionProtoType>();