mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 01:46:06 +00:00
When the exception specification for a function in an imported PCH or module is
resolved, emit an update record. llvm-svn: 204403
This commit is contained in:
parent
56b26a5707
commit
564417a071
@ -65,6 +65,10 @@ public:
|
||||
virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
|
||||
const FunctionDecl *D) {}
|
||||
|
||||
/// \brief A function's exception specification has been evaluated or
|
||||
/// instantiated.
|
||||
virtual void ResolvedExceptionSpec(const FunctionDecl *FD) {}
|
||||
|
||||
/// \brief A function's return type has been deduced.
|
||||
virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
|
||||
|
||||
|
@ -1128,6 +1128,8 @@ public:
|
||||
CanThrowResult canThrow(const Expr *E);
|
||||
const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc,
|
||||
const FunctionProtoType *FPT);
|
||||
void UpdateExceptionSpec(FunctionDecl *FD,
|
||||
const FunctionProtoType::ExtProtoInfo &EPI);
|
||||
bool CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range);
|
||||
bool CheckDistantExceptionSpec(QualType T);
|
||||
bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
|
||||
|
@ -1100,6 +1100,10 @@ private:
|
||||
};
|
||||
|
||||
QualType readTypeRecord(unsigned Index);
|
||||
void readExceptionSpec(ModuleFile &ModuleFile,
|
||||
SmallVectorImpl<QualType> &ExceptionStorage,
|
||||
FunctionProtoType::ExtProtoInfo &EPI,
|
||||
const RecordData &Record, unsigned &Index);
|
||||
RecordLocation TypeCursorForIndex(unsigned Index);
|
||||
void LoadedDecl(unsigned Index, Decl *D);
|
||||
Decl *ReadDeclRecord(serialization::DeclID ID);
|
||||
|
@ -758,6 +758,7 @@ public:
|
||||
const VarTemplateSpecializationDecl *D) override;
|
||||
void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
|
||||
const FunctionDecl *D) override;
|
||||
void ResolvedExceptionSpec(const FunctionDecl *FD) override;
|
||||
void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
|
||||
void CompletedImplicitDefinition(const FunctionDecl *D) override;
|
||||
void StaticDataMemberInstantiated(const VarDecl *D) override;
|
||||
|
@ -4659,15 +4659,6 @@ computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) {
|
||||
return S.ComputeInheritingCtorExceptionSpec(cast<CXXConstructorDecl>(MD));
|
||||
}
|
||||
|
||||
static void
|
||||
updateExceptionSpec(Sema &S, FunctionDecl *FD, const FunctionProtoType *FPT,
|
||||
const Sema::ImplicitExceptionSpecification &ExceptSpec) {
|
||||
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
||||
ExceptSpec.getEPI(EPI);
|
||||
FD->setType(S.Context.getFunctionType(FPT->getReturnType(),
|
||||
FPT->getParamTypes(), EPI));
|
||||
}
|
||||
|
||||
static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S,
|
||||
CXXMethodDecl *MD) {
|
||||
FunctionProtoType::ExtProtoInfo EPI;
|
||||
@ -4692,8 +4683,11 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD)
|
||||
ImplicitExceptionSpecification ExceptSpec =
|
||||
computeImplicitExceptionSpec(*this, Loc, MD);
|
||||
|
||||
FunctionProtoType::ExtProtoInfo EPI;
|
||||
ExceptSpec.getEPI(EPI);
|
||||
|
||||
// Update the type of the special member to use it.
|
||||
updateExceptionSpec(*this, MD, FPT, ExceptSpec);
|
||||
UpdateExceptionSpec(MD, EPI);
|
||||
|
||||
// A user-provided destructor can be defined outside the class. When that
|
||||
// happens, be sure to update the exception specification on both
|
||||
@ -4701,8 +4695,7 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD)
|
||||
const FunctionProtoType *CanonicalFPT =
|
||||
MD->getCanonicalDecl()->getType()->castAs<FunctionProtoType>();
|
||||
if (CanonicalFPT->getExceptionSpecType() == EST_Unevaluated)
|
||||
updateExceptionSpec(*this, MD->getCanonicalDecl(),
|
||||
CanonicalFPT, ExceptSpec);
|
||||
UpdateExceptionSpec(MD->getCanonicalDecl(), EPI);
|
||||
}
|
||||
|
||||
void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
|
||||
|
@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Sema/SemaInternal.h"
|
||||
#include "clang/AST/ASTMutationListener.h"
|
||||
#include "clang/AST/CXXInheritance.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
@ -132,6 +133,25 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
|
||||
return SourceDecl->getType()->castAs<FunctionProtoType>();
|
||||
}
|
||||
|
||||
void Sema::UpdateExceptionSpec(FunctionDecl *FD,
|
||||
const FunctionProtoType::ExtProtoInfo &EPI) {
|
||||
const FunctionProtoType *Proto = FD->getType()->castAs<FunctionProtoType>();
|
||||
|
||||
// Overwrite the exception spec and rebuild the function type.
|
||||
FunctionProtoType::ExtProtoInfo NewEPI = Proto->getExtProtoInfo();
|
||||
NewEPI.ExceptionSpecType = EPI.ExceptionSpecType;
|
||||
NewEPI.NumExceptions = EPI.NumExceptions;
|
||||
NewEPI.Exceptions = EPI.Exceptions;
|
||||
NewEPI.NoexceptExpr = EPI.NoexceptExpr;
|
||||
FD->setType(Context.getFunctionType(Proto->getReturnType(),
|
||||
Proto->getParamTypes(), NewEPI));
|
||||
|
||||
// If we've fully resolved the exception specification, notify listeners.
|
||||
if (!isUnresolvedExceptionSpec(EPI.ExceptionSpecType))
|
||||
if (auto *Listener = getASTMutationListener())
|
||||
Listener->ResolvedExceptionSpec(FD);
|
||||
}
|
||||
|
||||
/// Determine whether a function has an implicitly-generated exception
|
||||
/// specification.
|
||||
static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
|
||||
|
@ -3131,19 +3131,13 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild the function type
|
||||
const FunctionProtoType *NewProto
|
||||
= New->getType()->getAs<FunctionProtoType>();
|
||||
assert(NewProto && "Template instantiation without function prototype?");
|
||||
|
||||
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
|
||||
FunctionProtoType::ExtProtoInfo EPI;
|
||||
EPI.ExceptionSpecType = Proto->getExceptionSpecType();
|
||||
EPI.NumExceptions = Exceptions.size();
|
||||
EPI.Exceptions = Exceptions.data();
|
||||
EPI.NoexceptExpr = NoexceptExpr;
|
||||
|
||||
New->setType(SemaRef.Context.getFunctionType(NewProto->getReturnType(),
|
||||
NewProto->getParamTypes(), EPI));
|
||||
SemaRef.UpdateExceptionSpec(New, EPI);
|
||||
}
|
||||
|
||||
void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
|
||||
@ -3157,10 +3151,9 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
|
||||
if (Inst.isInvalid()) {
|
||||
// We hit the instantiation depth limit. Clear the exception specification
|
||||
// so that our callers don't have to cope with EST_Uninstantiated.
|
||||
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
|
||||
FunctionProtoType::ExtProtoInfo EPI;
|
||||
EPI.ExceptionSpecType = EST_None;
|
||||
Decl->setType(Context.getFunctionType(Proto->getReturnType(),
|
||||
Proto->getParamTypes(), EPI));
|
||||
UpdateExceptionSpec(Decl, EPI);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ enum DeclUpdateKind {
|
||||
UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
|
||||
UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
|
||||
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
|
||||
UPD_CXX_RESOLVED_EXCEPTION_SPEC,
|
||||
UPD_CXX_DEDUCED_RETURN_TYPE,
|
||||
UPD_DECL_MARKED_USED
|
||||
};
|
||||
|
@ -5036,23 +5036,8 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
|
||||
EPI.HasTrailingReturn = Record[Idx++];
|
||||
EPI.TypeQuals = Record[Idx++];
|
||||
EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
|
||||
ExceptionSpecificationType EST =
|
||||
static_cast<ExceptionSpecificationType>(Record[Idx++]);
|
||||
EPI.ExceptionSpecType = EST;
|
||||
SmallVector<QualType, 2> Exceptions;
|
||||
if (EST == EST_Dynamic) {
|
||||
EPI.NumExceptions = Record[Idx++];
|
||||
for (unsigned I = 0; I != EPI.NumExceptions; ++I)
|
||||
Exceptions.push_back(readType(*Loc.F, Record, Idx));
|
||||
EPI.Exceptions = Exceptions.data();
|
||||
} else if (EST == EST_ComputedNoexcept) {
|
||||
EPI.NoexceptExpr = ReadExpr(*Loc.F);
|
||||
} else if (EST == EST_Uninstantiated) {
|
||||
EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
|
||||
EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
|
||||
} else if (EST == EST_Unevaluated) {
|
||||
EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
|
||||
}
|
||||
SmallVector<QualType, 8> ExceptionStorage;
|
||||
readExceptionSpec(*Loc.F, ExceptionStorage, EPI, Record, Idx);
|
||||
return Context.getFunctionType(ResultType, ParamTypes, EPI);
|
||||
}
|
||||
|
||||
@ -5307,6 +5292,29 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
|
||||
llvm_unreachable("Invalid TypeCode!");
|
||||
}
|
||||
|
||||
void ASTReader::readExceptionSpec(ModuleFile &ModuleFile,
|
||||
SmallVectorImpl<QualType> &Exceptions,
|
||||
FunctionProtoType::ExtProtoInfo &EPI,
|
||||
const RecordData &Record, unsigned &Idx) {
|
||||
ExceptionSpecificationType EST =
|
||||
static_cast<ExceptionSpecificationType>(Record[Idx++]);
|
||||
EPI.ExceptionSpecType = EST;
|
||||
if (EST == EST_Dynamic) {
|
||||
EPI.NumExceptions = Record[Idx++];
|
||||
for (unsigned I = 0; I != EPI.NumExceptions; ++I)
|
||||
Exceptions.push_back(readType(ModuleFile, Record, Idx));
|
||||
EPI.Exceptions = Exceptions.data();
|
||||
} else if (EST == EST_ComputedNoexcept) {
|
||||
EPI.NoexceptExpr = ReadExpr(ModuleFile);
|
||||
} else if (EST == EST_Uninstantiated) {
|
||||
EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
|
||||
EPI.ExceptionSpecTemplate =
|
||||
ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
|
||||
} else if (EST == EST_Unevaluated) {
|
||||
EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
|
||||
}
|
||||
}
|
||||
|
||||
class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> {
|
||||
ASTReader &Reader;
|
||||
ModuleFile &F;
|
||||
|
@ -2944,6 +2944,17 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
|
||||
Reader.ReadSourceLocation(ModuleFile, Record, Idx));
|
||||
break;
|
||||
|
||||
case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
|
||||
auto *FD = cast<FunctionDecl>(D);
|
||||
auto *FPT = FD->getType()->castAs<FunctionProtoType>();
|
||||
auto EPI = FPT->getExtProtoInfo();
|
||||
SmallVector<QualType, 8> ExceptionStorage;
|
||||
Reader.readExceptionSpec(ModuleFile, ExceptionStorage, EPI, Record, Idx);
|
||||
FD->setType(Reader.Context.getFunctionType(FPT->getReturnType(),
|
||||
FPT->getParamTypes(), EPI));
|
||||
break;
|
||||
}
|
||||
|
||||
case UPD_CXX_DEDUCED_RETURN_TYPE: {
|
||||
FunctionDecl *FD = cast<FunctionDecl>(D);
|
||||
Reader.Context.adjustDeducedFunctionResultType(
|
||||
|
@ -194,15 +194,8 @@ void ASTTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
|
||||
Code = TYPE_FUNCTION_NO_PROTO;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
|
||||
VisitFunctionType(T);
|
||||
Record.push_back(T->getNumParams());
|
||||
for (unsigned I = 0, N = T->getNumParams(); I != N; ++I)
|
||||
Writer.AddTypeRef(T->getParamType(I), Record);
|
||||
Record.push_back(T->isVariadic());
|
||||
Record.push_back(T->hasTrailingReturn());
|
||||
Record.push_back(T->getTypeQuals());
|
||||
Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
|
||||
static void addExceptionSpec(ASTWriter &Writer, const FunctionProtoType *T,
|
||||
ASTWriter::RecordDataImpl &Record) {
|
||||
Record.push_back(T->getExceptionSpecType());
|
||||
if (T->getExceptionSpecType() == EST_Dynamic) {
|
||||
Record.push_back(T->getNumExceptions());
|
||||
@ -216,6 +209,18 @@ void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
|
||||
} else if (T->getExceptionSpecType() == EST_Unevaluated) {
|
||||
Writer.AddDeclRef(T->getExceptionSpecDecl(), Record);
|
||||
}
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
|
||||
VisitFunctionType(T);
|
||||
Record.push_back(T->getNumParams());
|
||||
for (unsigned I = 0, N = T->getNumParams(); I != N; ++I)
|
||||
Writer.AddTypeRef(T->getParamType(I), Record);
|
||||
Record.push_back(T->isVariadic());
|
||||
Record.push_back(T->hasTrailingReturn());
|
||||
Record.push_back(T->getTypeQuals());
|
||||
Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
|
||||
addExceptionSpec(Writer, T, Record);
|
||||
Code = TYPE_FUNCTION_PROTO;
|
||||
}
|
||||
|
||||
@ -4341,6 +4346,13 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
|
||||
AddSourceLocation(Update.getLoc(), Record);
|
||||
break;
|
||||
|
||||
case UPD_CXX_RESOLVED_EXCEPTION_SPEC:
|
||||
addExceptionSpec(
|
||||
*this,
|
||||
cast<FunctionDecl>(D)->getType()->castAs<FunctionProtoType>(),
|
||||
Record);
|
||||
break;
|
||||
|
||||
case UPD_CXX_DEDUCED_RETURN_TYPE:
|
||||
Record.push_back(GetOrCreateTypeID(Update.getType()));
|
||||
break;
|
||||
@ -5305,6 +5317,15 @@ void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
|
||||
DeclUpdates[TD].push_back({UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, D});
|
||||
}
|
||||
|
||||
void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
|
||||
assert(!WritingAST && "Already writing the AST!");
|
||||
FD = FD->getCanonicalDecl();
|
||||
if (!FD->isFromASTFile())
|
||||
return; // Not a function declared in PCH and defined outside.
|
||||
|
||||
DeclUpdates[FD].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC);
|
||||
}
|
||||
|
||||
void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
|
||||
assert(!WritingAST && "Already writing the AST!");
|
||||
FD = FD->getCanonicalDecl();
|
||||
|
@ -1,18 +1,47 @@
|
||||
// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t
|
||||
// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t -verify %s
|
||||
// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t.1
|
||||
// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t.1 -emit-pch %s -o %t.2
|
||||
// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t.2 -verify %s
|
||||
// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t.2 -emit-llvm-only %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER_INCLUDED
|
||||
#ifndef PHASE1_DONE
|
||||
#define PHASE1_DONE
|
||||
|
||||
#define HEADER_INCLUDED
|
||||
template<int n> int f() noexcept(n % 2) { return 0; }
|
||||
template<int n> int g() noexcept(n % 2);
|
||||
|
||||
template<bool b> int f() noexcept(b) {}
|
||||
decltype(f<false>()) a;
|
||||
decltype(f<true>()) b;
|
||||
decltype(f<2>()) f0;
|
||||
decltype(f<3>()) f1;
|
||||
template int f<4>();
|
||||
template int f<5>();
|
||||
decltype(f<6>()) f6;
|
||||
decltype(f<7>()) f7;
|
||||
|
||||
struct A {
|
||||
A();
|
||||
A(const A&);
|
||||
};
|
||||
|
||||
decltype(g<0>()) g0;
|
||||
|
||||
#elif !defined(PHASE2_DONE)
|
||||
#define PHASE2_DONE
|
||||
|
||||
template int f<6>();
|
||||
template int f<7>();
|
||||
decltype(f<8>()) f8;
|
||||
decltype(f<9>()) f9;
|
||||
template int f<10>();
|
||||
template int f<11>();
|
||||
|
||||
A::A() = default;
|
||||
A::A(const A&) = default;
|
||||
|
||||
int g0val = g<0>();
|
||||
|
||||
#else
|
||||
|
||||
static_assert(!noexcept(f<false>()), "");
|
||||
static_assert(noexcept(f<true>()), "");
|
||||
static_assert(!noexcept(f<0>()), "");
|
||||
static_assert(noexcept(f<1>()), "");
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user