summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ASTContext.h4
-rw-r--r--clang/lib/AST/ASTContext.cpp8
-rw-r--r--clang/lib/AST/ExprConstant.cpp5
-rw-r--r--clang/lib/Sema/SemaDecl.cpp31
-rw-r--r--clang/test/SemaCXX/constant-expression-cxx1z.cpp2
5 files changed, 28 insertions, 22 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 4f35508ebac..47d29bc2092 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1109,6 +1109,10 @@ public:
/// \brief Change the result type of a function type once it is deduced.
void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
+ /// \brief Determine whether two function types are the same, ignoring
+ /// exception specifications in cases where they're part of the type.
+ bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U);
+
/// \brief Change the exception specification on a function once it is
/// delay-parsed, instantiated, or computed.
void adjustExceptionSpec(FunctionDecl *FD,
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 22be71a7272..73ea66e98e8 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -2382,6 +2382,14 @@ static QualType getFunctionTypeWithExceptionSpec(
Proto->getExtProtoInfo().withExceptionSpec(ESI));
}
+bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T,
+ QualType U) {
+ return hasSameType(T, U) ||
+ (getLangOpts().CPlusPlus1z &&
+ hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None),
+ getFunctionTypeWithExceptionSpec(*this, U, EST_None)));
+}
+
void ASTContext::adjustExceptionSpec(
FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI,
bool AsWritten) {
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 5dd493cfff5..36f5e6aae55 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4434,8 +4434,11 @@ public:
}
// Don't call function pointers which have been cast to some other type.
- if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType()))
+ // Per DR (no number yet), the caller and callee can differ in noexcept.
+ if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec(
+ CalleeType->getPointeeType(), FD->getType())) {
return Error(E);
+ }
} else
return Error(E);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 89cb4398638..7878355fc19 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9076,27 +9076,16 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
ASTContext::GetBuiltinTypeError Error;
LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier());
QualType T = Context.GetBuiltinType(BuiltinID, Error);
- if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) {
- auto WithoutExceptionSpec = [&](QualType T) -> QualType {
- auto *Proto = T->getAs<FunctionProtoType>();
- if (!Proto)
- return T;
- return Context.getFunctionType(
- Proto->getReturnType(), Proto->getParamTypes(),
- Proto->getExtProtoInfo().withExceptionSpec(EST_None));
- };
-
- // If the type of the builtin differs only in its exception
- // specification, that's OK.
- // FIXME: If the types do differ in this way, it would be better to
- // retain the 'noexcept' form of the type.
- if (!getLangOpts().CPlusPlus1z ||
- !Context.hasSameType(WithoutExceptionSpec(T),
- WithoutExceptionSpec(NewFD->getType())))
- // The type of this function differs from the type of the builtin,
- // so forget about the builtin entirely.
- Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents);
- }
+ // If the type of the builtin differs only in its exception
+ // specification, that's OK.
+ // FIXME: If the types do differ in this way, it would be better to
+ // retain the 'noexcept' form of the type.
+ if (!T.isNull() &&
+ !Context.hasSameFunctionTypeIgnoringExceptionSpec(T,
+ NewFD->getType()))
+ // The type of this function differs from the type of the builtin,
+ // so forget about the builtin entirely.
+ Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents);
}
// If this function is declared as being extern "C", then check to see if
diff --git a/clang/test/SemaCXX/constant-expression-cxx1z.cpp b/clang/test/SemaCXX/constant-expression-cxx1z.cpp
index 1563586e196..a48c9b11b88 100644
--- a/clang/test/SemaCXX/constant-expression-cxx1z.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx1z.cpp
@@ -28,7 +28,9 @@ namespace BaseClassAggregateInit {
namespace NoexceptFunctionTypes {
template<typename T> constexpr bool f() noexcept(true) { return true; }
+ constexpr bool (*fp)() = f<int>;
static_assert(f<int>());
+ static_assert(fp());
template<typename T> struct A {
constexpr bool f() noexcept(true) { return true; }
OpenPOWER on IntegriCloud