forked from OSchip/llvm-project
[c++1z] Use canonical expression equivalence to determine whether two different
dependent noexcept specifications result in the same canonical function type. We still use non-canonical hashing when deduplicating type sugar so that diagnostics will point to the right place. llvm-svn: 284457
This commit is contained in:
parent
156f6cafc2
commit
99677afd54
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
Loading…
Reference in New Issue