Reintroduce the home for exception specs, and make Sema fill it. However, keep the spec out of the canonical type this time. Net effect is currently nothing, because the spec isn't checked anywhere.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72498 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 0db5f9b..b230edb 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1261,49 +1261,58 @@
/// list. isVariadic indicates whether the argument list includes '...'.
QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
unsigned NumArgs, bool isVariadic,
- unsigned TypeQuals) {
+ unsigned TypeQuals, bool hasExceptionSpec,
+ bool hasAnyExceptionSpec, unsigned NumExs,
+ const QualType *ExArray) {
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic,
- TypeQuals);
+ TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
+ NumExs, ExArray);
void *InsertPos = 0;
if (FunctionProtoType *FTP =
FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(FTP, 0);
-
- // Determine whether the type being created is already canonical or not.
+
+ // Determine whether the type being created is already canonical or not.
bool isCanonical = ResultTy->isCanonical();
+ if (hasExceptionSpec)
+ isCanonical = false;
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
if (!ArgArray[i]->isCanonical())
isCanonical = false;
// If this type isn't canonical, get the canonical version of it.
+ // The exception spec is not part of the canonical type.
QualType Canonical;
if (!isCanonical) {
llvm::SmallVector<QualType, 16> CanonicalArgs;
CanonicalArgs.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
CanonicalArgs.push_back(getCanonicalType(ArgArray[i]));
-
+
Canonical = getFunctionType(getCanonicalType(ResultTy),
CanonicalArgs.data(), NumArgs,
isVariadic, TypeQuals);
-
+
// Get the new insert position for the node we care about.
FunctionProtoType *NewIP =
FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
}
-
+
// FunctionProtoType objects are allocated with extra bytes after them
- // for a variable size array (for parameter types) at the end of them.
+ // for two variable size arrays (for parameter and exception types) at the
+ // end of them.
FunctionProtoType *FTP =
- (FunctionProtoType*)Allocate(sizeof(FunctionProtoType) +
- NumArgs*sizeof(QualType), 8);
+ (FunctionProtoType*)Allocate(sizeof(FunctionProtoType) +
+ NumArgs*sizeof(QualType) +
+ NumExs*sizeof(QualType), 8);
new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic,
- TypeQuals, Canonical);
+ TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
+ ExArray, NumExs, Canonical);
Types.push_back(FTP);
FunctionProtoTypes.InsertNode(FTP, InsertPos);
return QualType(FTP, 0);
@@ -2912,6 +2921,8 @@
allRTypes = false;
if (lproto && rproto) { // two C99 style function prototypes
+ assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
+ "C++ shouldn't be here");
unsigned lproto_nargs = lproto->getNumArgs();
unsigned rproto_nargs = rproto->getNumArgs();
@@ -2950,6 +2961,7 @@
const FunctionProtoType *proto = lproto ? lproto : rproto;
if (proto) {
+ assert(!proto->hasExceptionSpec() && "C++ shouldn't be here");
if (proto->isVariadic()) return QualType();
// Check that the types are compatible with the types that
// would result from default argument promotions (C99 6.7.5.3p15).
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 6093352..c04e827 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -927,17 +927,26 @@
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
arg_type_iterator ArgTys,
unsigned NumArgs, bool isVariadic,
- unsigned TypeQuals) {
+ unsigned TypeQuals, bool hasExceptionSpec,
+ bool anyExceptionSpec, unsigned NumExceptions,
+ exception_iterator Exs) {
ID.AddPointer(Result.getAsOpaquePtr());
for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
ID.AddInteger(isVariadic);
ID.AddInteger(TypeQuals);
+ ID.AddInteger(hasExceptionSpec);
+ if (hasExceptionSpec) {
+ ID.AddInteger(anyExceptionSpec);
+ for(unsigned i = 0; i != NumExceptions; ++i)
+ ID.AddPointer(Exs[i].getAsOpaquePtr());
+ }
}
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getResultType(), arg_type_begin(), NumArgs, isVariadic(),
- getTypeQuals());
+ getTypeQuals(), hasExceptionSpec(), hasAnyExceptionSpec(),
+ getNumExceptions(), exception_begin());
}
void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 46f4fb7..63e4337 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1670,8 +1670,16 @@
ParamTypes.push_back(GetType(Record[Idx++]));
bool isVariadic = Record[Idx++];
unsigned Quals = Record[Idx++];
+ bool hasExceptionSpec = Record[Idx++];
+ bool hasAnyExceptionSpec = Record[Idx++];
+ unsigned NumExceptions = Record[Idx++];
+ llvm::SmallVector<QualType, 2> Exceptions;
+ for (unsigned I = 0; I != NumExceptions; ++I)
+ Exceptions.push_back(GetType(Record[Idx++]));
return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
- isVariadic, Quals);
+ isVariadic, Quals, hasExceptionSpec,
+ hasAnyExceptionSpec, NumExceptions,
+ Exceptions.data());
}
case pch::TYPE_TYPEDEF:
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 2d3ca17..9f9b3b4 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -162,6 +162,11 @@
Writer.AddTypeRef(T->getArgType(I), Record);
Record.push_back(T->isVariadic());
Record.push_back(T->getTypeQuals());
+ Record.push_back(T->hasExceptionSpec());
+ Record.push_back(T->hasAnyExceptionSpec());
+ Record.push_back(T->getNumExceptions());
+ for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I)
+ Writer.AddTypeRef(T->getExceptionType(I), Record);
Code = pch::TYPE_FUNCTION_PROTO;
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index d592cf6..7b36b13 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -729,6 +729,7 @@
(OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
// The old declaration provided a function prototype, but the
// new declaration does not. Merge in the prototype.
+ assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
llvm::SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(),
OldProto->arg_type_end());
NewQType = Context.getFunctionType(NewFuncType->getResultType(),
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index ebe3406..6edb290 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -999,6 +999,9 @@
QualType ClassType = Context.getTypeDeclType(ClassDecl);
ClassType = Context.getCanonicalType(ClassType);
+ // FIXME: Implicit declarations have exception specifications, which are
+ // the union of the specifications of the implicitly called functions.
+
if (!ClassDecl->hasUserDeclaredConstructor()) {
// C++ [class.ctor]p5:
// A default constructor for a class X is a constructor of class X
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 19ff9bb..298a6cd 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -716,12 +716,20 @@
T = Context.IntTy;
D.setInvalidType(true);
}
-
+
if (FTI.NumArgs == 0) {
if (getLangOptions().CPlusPlus) {
// C++ 8.3.5p2: If the parameter-declaration-clause is empty, the
// function takes no arguments.
- T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic,FTI.TypeQuals);
+ llvm::SmallVector<QualType, 4> Exceptions;
+ Exceptions.reserve(FTI.NumExceptions);
+ for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei)
+ Exceptions.push_back(
+ QualType::getFromOpaquePtr(FTI.Exceptions[ei]));
+ T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, FTI.TypeQuals,
+ FTI.hasExceptionSpec,
+ FTI.hasAnyExceptionSpec,
+ FTI.NumExceptions, Exceptions.data());
} else if (FTI.isVariadic) {
// We allow a zero-parameter variadic function in C if the
// function is marked with the "overloadable"
@@ -795,8 +803,17 @@
ArgTys.push_back(ArgTy);
}
+
+ llvm::SmallVector<QualType, 4> Exceptions;
+ Exceptions.reserve(FTI.NumExceptions);
+ for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei)
+ Exceptions.push_back(QualType::getFromOpaquePtr(FTI.Exceptions[ei]));
+
T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(),
- FTI.isVariadic, FTI.TypeQuals);
+ FTI.isVariadic, FTI.TypeQuals,
+ FTI.hasExceptionSpec,
+ FTI.hasAnyExceptionSpec,
+ FTI.NumExceptions, Exceptions.data());
}
break;
}