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
This commit is contained in:
Sebastian Redl 2009-05-27 22:11:52 +00:00
Родитель cfcceab862
Коммит 465226e23a
9 изменённых файлов: 128 добавлений и 31 удалений

Просмотреть файл

@ -287,12 +287,14 @@ public:
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType getFunctionNoProtoType(QualType ResultTy);
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
QualType getFunctionType(QualType ResultTy, const QualType *ArgArray,
unsigned NumArgs, bool isVariadic,
unsigned TypeQuals);
unsigned TypeQuals, bool hasExceptionSpec = false,
bool hasAnyExceptionSpec = false,
unsigned NumExs = 0, const QualType *ExArray = 0);
/// getTypeDeclType - Return the unique reference to the type for
/// the specified type declaration.

Просмотреть файл

@ -1151,7 +1151,9 @@ public:
/// FunctionProtoType - Represents a prototype with argument type info, e.g.
/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no
/// arguments, not as having a single void argument.
/// arguments, not as having a single void argument. Such a type can have an
/// exception specification, but this specification is not part of the canonical
/// type.
class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
/// hasAnyDependentType - Determine whether there are any dependent
/// types within the arguments passed in.
@ -1164,23 +1166,42 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
}
FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs,
bool isVariadic, unsigned typeQuals, QualType Canonical)
bool isVariadic, unsigned typeQuals, bool hasExs,
bool hasAnyExs, const QualType *ExArray,
unsigned numExs, QualType Canonical)
: FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
(Result->isDependentType() ||
hasAnyDependentType(ArgArray, numArgs))),
NumArgs(numArgs) {
NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
AnyExceptionSpec(hasAnyExs) {
// Fill in the trailing argument array.
QualType *ArgInfo = reinterpret_cast<QualType *>(this+1);;
QualType *ArgInfo = reinterpret_cast<QualType*>(this+1);
for (unsigned i = 0; i != numArgs; ++i)
ArgInfo[i] = ArgArray[i];
// Fill in the exception array.
QualType *Ex = ArgInfo + numArgs;
for (unsigned i = 0; i != numExs; ++i)
Ex[i] = ExArray[i];
}
/// NumArgs - The number of arguments this function has, not counting '...'.
unsigned NumArgs;
unsigned NumArgs : 20;
/// NumExceptions - The number of types in the exception spec, if any.
unsigned NumExceptions : 10;
/// HasExceptionSpec - Whether this function has an exception spec at all.
bool HasExceptionSpec : 1;
/// AnyExceptionSpec - Whether this function has a throw(...) spec.
bool AnyExceptionSpec : 1;
/// ArgInfo - There is an variable size array after the class in memory that
/// holds the argument types.
/// Exceptions - There is another variable size array after ArgInfo that
/// holds the exception types.
friend class ASTContext; // ASTContext creates these.
public:
@ -1189,7 +1210,15 @@ public:
assert(i < NumArgs && "Invalid argument number!");
return arg_type_begin()[i];
}
bool hasExceptionSpec() const { return HasExceptionSpec; }
bool hasAnyExceptionSpec() const { return AnyExceptionSpec; }
unsigned getNumExceptions() const { return NumExceptions; }
QualType getExceptionType(unsigned i) const {
assert(i < NumExceptions && "Invalid exception number!");
return exception_begin()[i];
}
bool isVariadic() const { return getSubClassData(); }
unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
@ -1198,18 +1227,29 @@ public:
return reinterpret_cast<const QualType *>(this+1);
}
arg_type_iterator arg_type_end() const { return arg_type_begin()+NumArgs; }
typedef const QualType *exception_iterator;
exception_iterator exception_begin() const {
// exceptions begin where arguments end
return arg_type_end();
}
exception_iterator exception_end() const {
return exception_begin() + NumExceptions;
}
virtual void getAsStringInternal(std::string &InnerString) const;
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionProto;
}
static bool classof(const FunctionProtoType *) { return true; }
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
arg_type_iterator ArgTys, unsigned NumArgs,
bool isVariadic, unsigned TypeQuals);
bool isVariadic, unsigned TypeQuals,
bool hasExceptionSpec, bool anyExceptionSpec,
unsigned NumExceptions, exception_iterator Exs);
};

Просмотреть файл

@ -1261,49 +1261,58 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy) {
/// 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 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
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 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
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).

Просмотреть файл

@ -927,17 +927,26 @@ const char *BuiltinType::getName() const {
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,

Просмотреть файл

@ -1670,8 +1670,16 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
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:

Просмотреть файл

@ -162,6 +162,11 @@ void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
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;
}

Просмотреть файл

@ -729,6 +729,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
(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(),

Просмотреть файл

@ -999,6 +999,9 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
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

Просмотреть файл

@ -716,12 +716,20 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
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 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
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;
}