r204403 - When the exception specification for a function in an imported PCH or module is
Richard Smith
richard-llvm at metafoo.co.uk
Thu Mar 20 14:47:22 PDT 2014
Author: rsmith
Date: Thu Mar 20 16:47:22 2014
New Revision: 204403
URL: http://llvm.org/viewvc/llvm-project?rev=204403&view=rev
Log:
When the exception specification for a function in an imported PCH or module is
resolved, emit an update record.
Modified:
cfe/trunk/include/clang/AST/ASTMutationListener.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/include/clang/Serialization/ASTReader.h
cfe/trunk/include/clang/Serialization/ASTWriter.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Serialization/ASTCommon.h
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/test/PCH/cxx11-exception-spec.cpp
Modified: cfe/trunk/include/clang/AST/ASTMutationListener.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTMutationListener.h?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTMutationListener.h (original)
+++ cfe/trunk/include/clang/AST/ASTMutationListener.h Thu Mar 20 16:47:22 2014
@@ -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);
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Mar 20 16:47:22 2014
@@ -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);
Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Thu Mar 20 16:47:22 2014
@@ -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);
Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Thu Mar 20 16:47:22 2014
@@ -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;
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Mar 20 16:47:22 2014
@@ -4659,15 +4659,6 @@ computeImplicitExceptionSpec(Sema &S, So
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
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
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) {
Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Thu Mar 20 16:47:22 2014
@@ -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(SourceLocatio
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) {
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Mar 20 16:47:22 2014
@@ -3131,19 +3131,13 @@ static void InstantiateExceptionSpec(Sem
}
}
- // 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(Sour
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;
}
Modified: cfe/trunk/lib/Serialization/ASTCommon.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.h?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.h (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.h Thu Mar 20 16:47:22 2014
@@ -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
};
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Mar 20 16:47:22 2014
@@ -5036,23 +5036,8 @@ QualType ASTReader::readTypeRecord(unsig
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(unsig
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;
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Mar 20 16:47:22 2014
@@ -2944,6 +2944,17 @@ void ASTDeclReader::UpdateDecl(Decl *D,
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(
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Mar 20 16:47:22 2014
@@ -194,15 +194,8 @@ void ASTTypeWriter::VisitFunctionNoProto
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::VisitFunctionProtoTy
} 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(R
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::AddedCXXTemplateSpeciali
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();
Modified: cfe/trunk/test/PCH/cxx11-exception-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx11-exception-spec.cpp?rev=204403&r1=204402&r2=204403&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx11-exception-spec.cpp (original)
+++ cfe/trunk/test/PCH/cxx11-exception-spec.cpp Thu Mar 20 16:47:22 2014
@@ -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
More information about the cfe-commits
mailing list