diff options
| -rw-r--r-- | clang/include/clang/AST/Type.h | 3 | ||||
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 22 | ||||
| -rw-r--r-- | clang/lib/AST/Type.cpp | 6 | ||||
| -rw-r--r-- | clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp | 13 | 
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);  | 

