summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/Type.h3
-rw-r--r--clang/lib/AST/ASTContext.cpp22
-rw-r--r--clang/lib/AST/Type.cpp6
-rw-r--r--clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp13
4 files changed, 29 insertions, 15 deletions
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index e9351a9e514..691a7dca3a1 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -3473,7 +3473,8 @@ public:
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
param_type_iterator ArgTys, unsigned NumArgs,
- const ExtProtoInfo &EPI, const ASTContext &Context);
+ const ExtProtoInfo &EPI, const ASTContext &Context,
+ bool Canonical);
};
/// \brief Represents the dependent type named by a dependently-scoped
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 3da1c74bc12..d2f01c0c12d 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3170,17 +3170,6 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
const FunctionProtoType::ExtProtoInfo &EPI) const {
size_t NumArgs = ArgArray.size();
- // Unique functions, to guarantee there is only one function of a particular
- // structure.
- llvm::FoldingSetNodeID ID;
- FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI,
- *this);
-
- void *InsertPos = nullptr;
- if (FunctionProtoType *FTP =
- FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(FTP, 0);
-
bool NoexceptInType = getLangOpts().CPlusPlus1z;
bool IsCanonicalExceptionSpec =
@@ -3193,6 +3182,17 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
if (!ArgArray[i].isCanonicalAsParam())
isCanonical = false;
+ // Unique functions, to guarantee there is only one function of a particular
+ // structure.
+ llvm::FoldingSetNodeID ID;
+ FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI,
+ *this, isCanonical);
+
+ void *InsertPos = nullptr;
+ if (FunctionProtoType *FTP =
+ FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(FTP, 0);
+
// If this type isn't canonical, get the canonical version of it.
// The exception spec is not part of the canonical type.
QualType Canonical;
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 2601fa44ccc..3e776e30438 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2850,7 +2850,7 @@ bool FunctionProtoType::isTemplateVariadic() const {
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
const QualType *ArgTys, unsigned NumParams,
const ExtProtoInfo &epi,
- const ASTContext &Context) {
+ const ASTContext &Context, bool Canonical) {
// We have to be careful not to get ambiguous profile encodings.
// Note that valid type pointers are never ambiguous with anything else.
@@ -2889,7 +2889,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
ID.AddPointer(Ex.getAsOpaquePtr());
} else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept &&
epi.ExceptionSpec.NoexceptExpr) {
- epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, false);
+ epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, Canonical);
} else if (epi.ExceptionSpec.Type == EST_Uninstantiated ||
epi.ExceptionSpec.Type == EST_Unevaluated) {
ID.AddPointer(epi.ExceptionSpec.SourceDecl->getCanonicalDecl());
@@ -2905,7 +2905,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Ctx) {
Profile(ID, getReturnType(), param_type_begin(), NumParams, getExtProtoInfo(),
- Ctx);
+ Ctx, isCanonicalUnqualified());
}
QualType TypedefType::desugar() const {
diff --git a/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
new file mode 100644
index 00000000000..e2a947eac05
--- /dev/null
+++ b/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-note {{previous}}
+template<typename T> void redecl1() noexcept(noexcept(T())); // ok, same type
+template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-error {{redefinition}}
+
+template<bool A, bool B> void redecl2() noexcept(A); // expected-note {{previous}}
+template<bool A, bool B> void redecl2() noexcept(B); // expected-error {{conflicting types}}
+
+// These have the same canonical type.
+// FIXME: It's not clear whether this is supposed to be valid.
+template<typename A, typename B> void redecl3() throw(A);
+template<typename A, typename B> void redecl3() throw(B);
OpenPOWER on IntegriCloud