aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp204
1 files changed, 89 insertions, 115 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
index 1a5f4824d091..3e8f324027dc 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -181,13 +181,13 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
return false;
}
- // The failure was something other than an empty exception
+ // The failure was something other than an missing exception
// specification; return an error.
- if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification)
+ if (!MissingExceptionSpecification)
return true;
const FunctionProtoType *NewProto =
- New->getType()->getAs<FunctionProtoType>();
+ New->getType()->castAs<FunctionProtoType>();
// The new function declaration is only missing an empty exception
// specification "throw()". If the throw() specification came from a
@@ -203,123 +203,94 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
Old->isExternC()) {
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
EPI.ExceptionSpecType = EST_DynamicNone;
- QualType NewType =
- Context.getFunctionType(NewProto->getResultType(),
- ArrayRef<QualType>(NewProto->arg_type_begin(),
- NewProto->getNumArgs()),
- EPI);
+ QualType NewType = Context.getFunctionType(NewProto->getResultType(),
+ NewProto->getArgTypes(), EPI);
New->setType(NewType);
return false;
}
- if (MissingExceptionSpecification && NewProto) {
- const FunctionProtoType *OldProto =
- Old->getType()->getAs<FunctionProtoType>();
-
- FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
- EPI.ExceptionSpecType = OldProto->getExceptionSpecType();
- if (EPI.ExceptionSpecType == EST_Dynamic) {
- EPI.NumExceptions = OldProto->getNumExceptions();
- EPI.Exceptions = OldProto->exception_begin();
- } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
- // FIXME: We can't just take the expression from the old prototype. It
- // likely contains references to the old prototype's parameters.
- }
-
- // Update the type of the function with the appropriate exception
- // specification.
- QualType NewType =
- Context.getFunctionType(NewProto->getResultType(),
- ArrayRef<QualType>(NewProto->arg_type_begin(),
- NewProto->getNumArgs()),
- EPI);
- New->setType(NewType);
-
- // If exceptions are disabled, suppress the warning about missing
- // exception specifications for new and delete operators.
- if (!getLangOpts().CXXExceptions) {
- switch (New->getDeclName().getCXXOverloadedOperator()) {
- case OO_New:
- case OO_Array_New:
- case OO_Delete:
- case OO_Array_Delete:
- if (New->getDeclContext()->isTranslationUnit())
- return false;
- break;
-
- default:
- break;
- }
- }
-
- // Warn about the lack of exception specification.
- SmallString<128> ExceptionSpecString;
- llvm::raw_svector_ostream OS(ExceptionSpecString);
- switch (OldProto->getExceptionSpecType()) {
- case EST_DynamicNone:
- OS << "throw()";
- break;
+ const FunctionProtoType *OldProto =
+ Old->getType()->castAs<FunctionProtoType>();
+
+ FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+ EPI.ExceptionSpecType = OldProto->getExceptionSpecType();
+ if (EPI.ExceptionSpecType == EST_Dynamic) {
+ EPI.NumExceptions = OldProto->getNumExceptions();
+ EPI.Exceptions = OldProto->exception_begin();
+ } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
+ // FIXME: We can't just take the expression from the old prototype. It
+ // likely contains references to the old prototype's parameters.
+ }
- case EST_Dynamic: {
- OS << "throw(";
- bool OnFirstException = true;
- for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(),
- EEnd = OldProto->exception_end();
- E != EEnd;
- ++E) {
- if (OnFirstException)
- OnFirstException = false;
- else
- OS << ", ";
-
- OS << E->getAsString(getPrintingPolicy());
- }
- OS << ")";
- break;
+ // Update the type of the function with the appropriate exception
+ // specification.
+ QualType NewType = Context.getFunctionType(NewProto->getResultType(),
+ NewProto->getArgTypes(), EPI);
+ New->setType(NewType);
+
+ // Warn about the lack of exception specification.
+ SmallString<128> ExceptionSpecString;
+ llvm::raw_svector_ostream OS(ExceptionSpecString);
+ switch (OldProto->getExceptionSpecType()) {
+ case EST_DynamicNone:
+ OS << "throw()";
+ break;
+
+ case EST_Dynamic: {
+ OS << "throw(";
+ bool OnFirstException = true;
+ for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(),
+ EEnd = OldProto->exception_end();
+ E != EEnd;
+ ++E) {
+ if (OnFirstException)
+ OnFirstException = false;
+ else
+ OS << ", ";
+
+ OS << E->getAsString(getPrintingPolicy());
}
+ OS << ")";
+ break;
+ }
- case EST_BasicNoexcept:
- OS << "noexcept";
- break;
-
- case EST_ComputedNoexcept:
- OS << "noexcept(";
- OldProto->getNoexceptExpr()->printPretty(OS, 0, getPrintingPolicy());
- OS << ")";
- break;
+ case EST_BasicNoexcept:
+ OS << "noexcept";
+ break;
- default:
- llvm_unreachable("This spec type is compatible with none.");
- }
- OS.flush();
+ case EST_ComputedNoexcept:
+ OS << "noexcept(";
+ OldProto->getNoexceptExpr()->printPretty(OS, 0, getPrintingPolicy());
+ OS << ")";
+ break;
- SourceLocation FixItLoc;
- if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
- TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
- if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>())
- FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd());
- }
-
- if (FixItLoc.isInvalid())
- Diag(New->getLocation(), diag::warn_missing_exception_specification)
- << New << OS.str();
- else {
- // FIXME: This will get more complicated with C++0x
- // late-specified return types.
- Diag(New->getLocation(), diag::warn_missing_exception_specification)
- << New << OS.str()
- << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
- }
+ default:
+ llvm_unreachable("This spec type is compatible with none.");
+ }
+ OS.flush();
- if (!Old->getLocation().isInvalid())
- Diag(Old->getLocation(), diag::note_previous_declaration);
+ SourceLocation FixItLoc;
+ if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
+ TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
+ if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>())
+ FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd());
+ }
- return false;
+ if (FixItLoc.isInvalid())
+ Diag(New->getLocation(), diag::warn_missing_exception_specification)
+ << New << OS.str();
+ else {
+ // FIXME: This will get more complicated with C++0x
+ // late-specified return types.
+ Diag(New->getLocation(), diag::warn_missing_exception_specification)
+ << New << OS.str()
+ << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
}
- Diag(New->getLocation(), DiagID);
- Diag(Old->getLocation(), diag::note_previous_declaration);
- return true;
+ if (!Old->getLocation().isInvalid())
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+
+ return false;
}
/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
@@ -819,11 +790,8 @@ static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) {
return R;
}
-static CanThrowResult canCalleeThrow(Sema &S, const Expr *E,
- const Decl *D,
- bool NullThrows = true) {
- if (!D)
- return NullThrows ? CT_Can : CT_Cannot;
+static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) {
+ assert(D && "Expected decl");
// See if we can get a function type from the decl somehow.
const ValueDecl *VD = dyn_cast<ValueDecl>(D);
@@ -927,8 +895,10 @@ CanThrowResult Sema::canThrow(const Expr *E) {
CT = CT_Dependent;
else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
CT = CT_Cannot;
- else
+ else if (CE->getCalleeDecl())
CT = canCalleeThrow(*this, E, CE->getCalleeDecl());
+ else
+ CT = CT_Can;
if (CT == CT_Can)
return CT;
return mergeCanThrow(CT, canSubExprsThrow(*this, E));
@@ -974,7 +944,9 @@ CanThrowResult Sema::canThrow(const Expr *E) {
cast<CXXDeleteExpr>(E)->getOperatorDelete());
if (const RecordType *RT = DTy->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- CT = mergeCanThrow(CT, canCalleeThrow(*this, E, RD->getDestructor()));
+ const CXXDestructorDecl *DD = RD->getDestructor();
+ if (DD)
+ CT = mergeCanThrow(CT, canCalleeThrow(*this, E, DD));
}
if (CT == CT_Can)
return CT;
@@ -1012,6 +984,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::CompoundLiteralExprClass:
case Expr::CXXConstCastExprClass:
case Expr::CXXReinterpretCastExprClass:
+ case Expr::CXXStdInitializerListExprClass:
case Expr::DesignatedInitExprClass:
case Expr::ExprWithCleanupsClass:
case Expr::ExtVectorElementExprClass:
@@ -1022,6 +995,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::ParenExprClass:
case Expr::ParenListExprClass:
case Expr::ShuffleVectorExprClass:
+ case Expr::ConvertVectorExprClass:
case Expr::VAArgExprClass:
return canSubExprsThrow(*this, E);
@@ -1052,7 +1026,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::ChooseExprClass:
if (E->isTypeDependent() || E->isValueDependent())
return CT_Dependent;
- return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr(Context));
+ return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr());
case Expr::GenericSelectionExprClass:
if (cast<GenericSelectionExpr>(E)->isResultDependent())