aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaDecl.cpp14
-rw-r--r--lib/Sema/SemaDeclCXX.cpp2
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp55
-rw-r--r--lib/Sema/SemaType.cpp16
4 files changed, 52 insertions, 35 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f55415996b..162c50b7fe 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -5519,6 +5519,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
diag::err_static_out_of_line)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
}
+
+ // C++11 [except.spec]p15:
+ // A deallocation function with no exception-specification is treated
+ // as if it were specified with noexcept(true).
+ const FunctionProtoType *FPT = R->getAs<FunctionProtoType>();
+ if ((Name.getCXXOverloadedOperator() == OO_Delete ||
+ Name.getCXXOverloadedOperator() == OO_Array_Delete) &&
+ getLangOpts().CPlusPlus0x && FPT && !FPT->hasExceptionSpec()) {
+ FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+ EPI.ExceptionSpecType = EST_BasicNoexcept;
+ NewFD->setType(Context.getFunctionType(FPT->getResultType(),
+ FPT->arg_type_begin(),
+ FPT->getNumArgs(), EPI));
+ }
}
// Filter out previous declarations that don't match the scope.
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 0adcfc1520..f0bd810574 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -9379,7 +9379,7 @@ CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
}
static bool
-CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
+CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
// C++ [basic.stc.dynamic.deallocation]p1:
// A program is ill-formed if deallocation functions are declared in a
// namespace scope other than global scope or declared static in global
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index e35badc9f3..e1f4888d63 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -120,21 +120,22 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
return SourceDecl->getType()->castAs<FunctionProtoType>();
}
-/// Get the type that a function had prior to adjustment of the exception
+/// Determine whether a function has an implicitly-generated exception
/// specification.
-static const FunctionProtoType *getUnadjustedFunctionType(FunctionDecl *Decl) {
- if (isa<CXXDestructorDecl>(Decl) && Decl->getTypeSourceInfo()) {
- const FunctionProtoType *Ty =
- Decl->getTypeSourceInfo()->getType()->getAs<FunctionProtoType>();
- if (!Ty->hasExceptionSpec())
- // The type will be adjusted. Use the EST_None exception specification
- // from the type as written.
- return Ty;
- }
+static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
+ if (!isa<CXXDestructorDecl>(Decl) &&
+ Decl->getDeclName().getCXXOverloadedOperator() != OO_Delete &&
+ Decl->getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
+ return false;
+
+ // If the user didn't declare the function, its exception specification must
+ // be implicit.
+ if (!Decl->getTypeSourceInfo())
+ return true;
- // Use whatever type the function now has. The TypeSourceInfo does not contain
- // an instantiated exception specification for a function template,
- return Decl->getType()->getAs<FunctionProtoType>();
+ const FunctionProtoType *Ty =
+ Decl->getTypeSourceInfo()->getType()->getAs<FunctionProtoType>();
+ return !Ty->hasExceptionSpec();
}
bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
@@ -150,18 +151,31 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// specification adjustment is applied.
if (!CheckEquivalentExceptionSpec(
PDiag(DiagID), PDiag(diag::note_previous_declaration),
- getUnadjustedFunctionType(Old), Old->getLocation(),
- getUnadjustedFunctionType(New), New->getLocation(),
+ Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(),
+ New->getType()->getAs<FunctionProtoType>(), New->getLocation(),
&MissingExceptionSpecification, &MissingEmptyExceptionSpecification,
- /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew))
+ /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew)) {
+ // C++11 [except.spec]p4 [DR1492]:
+ // If a declaration of a function has an implicit
+ // exception-specification, other declarations of the function shall
+ // not specify an exception-specification.
+ if (getLangOpts().CPlusPlus0x &&
+ hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) {
+ Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch)
+ << hasImplicitExceptionSpec(Old);
+ if (!Old->getLocation().isInvalid())
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
return false;
+ }
// The failure was something other than an empty exception
// specification; return an error.
if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification)
return true;
- const FunctionProtoType *NewProto = getUnadjustedFunctionType(New);
+ const FunctionProtoType *NewProto =
+ New->getType()->getAs<FunctionProtoType>();
// The new function declaration is only missing an empty exception
// specification "throw()". If the throw() specification came from a
@@ -186,7 +200,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
}
if (MissingExceptionSpecification && NewProto) {
- const FunctionProtoType *OldProto = getUnadjustedFunctionType(Old);
+ const FunctionProtoType *OldProto =
+ Old->getType()->getAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
EPI.ExceptionSpecType = OldProto->getExceptionSpecType();
@@ -310,6 +325,10 @@ bool Sema::CheckEquivalentExceptionSpec(
/// CheckEquivalentExceptionSpec - Check if the two types have compatible
/// exception specifications. See C++ [except.spec]p3.
+///
+/// \return \c false if the exception specifications match, \c true if there is
+/// a problem. If \c true is returned, either a diagnostic has already been
+/// produced or \c *MissingExceptionSpecification is set to \c true.
bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
const PartialDiagnostic & NoteID,
const FunctionProtoType *Old,
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index a5c809d9f4..22da2164df 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -2169,16 +2169,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
ASTContext &Context = S.Context;
const LangOptions &LangOpts = S.getLangOpts();
- bool ImplicitlyNoexcept = false;
- if (D.getName().getKind() == UnqualifiedId::IK_OperatorFunctionId &&
- LangOpts.CPlusPlus0x) {
- OverloadedOperatorKind OO = D.getName().OperatorFunctionId.Operator;
- /// In C++0x, deallocation functions (normal and array operator delete)
- /// are implicitly noexcept.
- if (OO == OO_Delete || OO == OO_Array_Delete)
- ImplicitlyNoexcept = true;
- }
-
// The name we're declaring, if any.
DeclarationName Name;
if (D.getIdentifier())
@@ -2578,12 +2568,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
Exceptions,
EPI);
- if (FTI.getExceptionSpecType() == EST_None &&
- ImplicitlyNoexcept && chunkIndex == 0) {
- // Only the outermost chunk is marked noexcept, of course.
- EPI.ExceptionSpecType = EST_BasicNoexcept;
- }
-
T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI);
}