From db40c7f57326f6c6f08e0b9e397dd2aff98c4c3a Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 14 Dec 2010 08:05:40 +0000 Subject: [PATCH] Restore r121752 without modification. llvm-svn: 121763 --- clang/include/clang/AST/ASTContext.h | 13 +- clang/include/clang/AST/ExprCXX.h | 17 +-- clang/include/clang/AST/Type.h | 61 +++++++--- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/AST/ASTContext.cpp | 105 ++++++++--------- clang/lib/AST/ASTImporter.cpp | 12 +- clang/lib/AST/ExprCXX.cpp | 19 +++ clang/lib/AST/Type.cpp | 66 +++++------ clang/lib/CodeGen/CodeGenFunction.cpp | 11 +- clang/lib/Rewrite/RewriteObjC.cpp | 111 +++++++----------- clang/lib/Sema/SemaDecl.cpp | 17 ++- clang/lib/Sema/SemaDeclCXX.cpp | 95 +++++++-------- clang/lib/Sema/SemaExceptionSpec.cpp | 35 +++--- clang/lib/Sema/SemaExpr.cpp | 22 ++-- clang/lib/Sema/SemaExprCXX.cpp | 24 ++-- clang/lib/Sema/SemaLookup.cpp | 11 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 15 +-- clang/lib/Sema/SemaType.cpp | 49 +++++--- clang/lib/Serialization/ASTReader.cpp | 29 ++--- 19 files changed, 347 insertions(+), 367 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 745b6a38db60..70a852d9dd0b 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -626,14 +626,11 @@ public: return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo()); } - /// 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, bool hasExceptionSpec, - bool hasAnyExceptionSpec, - unsigned NumExs, const QualType *ExArray, - const FunctionType::ExtInfo &Info); + /// getFunctionType - Return a normal function type with a typed + /// argument list. + QualType getFunctionType(QualType ResultTy, + const QualType *Args, unsigned NumArgs, + const FunctionProtoType::ExtProtoInfo &EPI); /// getTypeDeclType - Return the unique reference to the type for /// the specified type declaration. diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index a822bcaffeb5..6b18561424cf 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1278,22 +1278,7 @@ public: TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc, SourceLocation TildeLoc, - PseudoDestructorTypeStorage DestroyedType) - : Expr(CXXPseudoDestructorExprClass, - Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, - false, 0, false, - false, 0, 0, - FunctionType::ExtInfo())), - VK_RValue, OK_Ordinary, - /*isTypeDependent=*/(Base->isTypeDependent() || - (DestroyedType.getTypeSourceInfo() && - DestroyedType.getTypeSourceInfo()->getType()->isDependentType())), - /*isValueDependent=*/Base->isValueDependent()), - Base(static_cast(Base)), IsArrow(isArrow), - OperatorLoc(OperatorLoc), Qualifier(Qualifier), - QualifierRange(QualifierRange), - ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc), - DestroyedType(DestroyedType) { } + PseudoDestructorTypeStorage DestroyedType); explicit CXXPseudoDestructorExpr(EmptyShell Shell) : Expr(CXXPseudoDestructorExprClass, Shell), diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index ba588ec1aae2..686331f44cbd 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -925,8 +925,8 @@ protected: /// regparm and the calling convention. unsigned ExtInfo : 8; - /// A bit to be used by the subclass. - unsigned SubclassInfo : 1; + /// Whether the function is variadic. Only used by FunctionProtoType. + unsigned Variadic : 1; /// TypeQuals - Used only by FunctionProtoType, put here to pack with the /// other bitfields. @@ -2196,13 +2196,13 @@ class FunctionType : public Type { return ExtInfo((Bits & ~CallConvMask) | (unsigned) cc); } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Bits); } }; protected: - FunctionType(TypeClass tc, QualType res, bool SubclassInfo, + FunctionType(TypeClass tc, QualType res, bool variadic, unsigned typeQuals, QualType Canonical, bool Dependent, bool VariablyModified, bool ContainsUnexpandedParameterPack, ExtInfo Info) @@ -2210,10 +2210,10 @@ protected: ContainsUnexpandedParameterPack), ResultType(res) { FunctionTypeBits.ExtInfo = Info.Bits; - FunctionTypeBits.SubclassInfo = SubclassInfo; + FunctionTypeBits.Variadic = variadic; FunctionTypeBits.TypeQuals = typeQuals; } - bool getSubClassData() const { return FunctionTypeBits.SubclassInfo; } + bool isVariadic() const { return FunctionTypeBits.Variadic; } unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } public: @@ -2276,6 +2276,23 @@ public: /// exception specification, but this specification is not part of the canonical /// type. class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { +public: + /// ExtProtoInfo - Extra information about a function prototype. + struct ExtProtoInfo { + ExtProtoInfo() : + Variadic(false), HasExceptionSpec(false), HasAnyExceptionSpec(false), + TypeQuals(0), NumExceptions(0), Exceptions(0) {} + + FunctionType::ExtInfo ExtInfo; + bool Variadic; + bool HasExceptionSpec; + bool HasAnyExceptionSpec; + unsigned char TypeQuals; + unsigned NumExceptions; + const QualType *Exceptions; + }; + +private: /// \brief Determine whether there are any argument types that /// contain an unexpanded parameter pack. static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray, @@ -2287,11 +2304,8 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { return false; } - FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs, - bool isVariadic, unsigned typeQuals, bool hasExs, - bool hasAnyExs, const QualType *ExArray, - unsigned numExs, QualType Canonical, - const ExtInfo &Info); + FunctionProtoType(QualType result, const QualType *args, unsigned numArgs, + QualType canonical, const ExtProtoInfo &epi); /// NumArgs - The number of arguments this function has, not counting '...'. unsigned NumArgs : 20; @@ -2302,8 +2316,8 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { /// HasExceptionSpec - Whether this function has an exception spec at all. unsigned HasExceptionSpec : 1; - /// AnyExceptionSpec - Whether this function has a throw(...) spec. - unsigned AnyExceptionSpec : 1; + /// HasAnyExceptionSpec - Whether this function has a throw(...) spec. + unsigned HasAnyExceptionSpec : 1; /// ArgInfo - There is an variable size array after the class in memory that /// holds the argument types. @@ -2320,8 +2334,20 @@ public: return arg_type_begin()[i]; } + ExtProtoInfo getExtProtoInfo() const { + ExtProtoInfo EPI; + EPI.ExtInfo = getExtInfo(); + EPI.Variadic = isVariadic(); + EPI.HasExceptionSpec = hasExceptionSpec(); + EPI.HasAnyExceptionSpec = hasAnyExceptionSpec(); + EPI.TypeQuals = static_cast(getTypeQuals()); + EPI.NumExceptions = NumExceptions; + EPI.Exceptions = exception_begin(); + return EPI; + } + bool hasExceptionSpec() const { return HasExceptionSpec; } - bool hasAnyExceptionSpec() const { return AnyExceptionSpec; } + bool hasAnyExceptionSpec() const { return HasAnyExceptionSpec; } unsigned getNumExceptions() const { return NumExceptions; } QualType getExceptionType(unsigned i) const { assert(i < NumExceptions && "Invalid exception number!"); @@ -2332,7 +2358,7 @@ public: getNumExceptions() == 0; } - bool isVariadic() const { return getSubClassData(); } + using FunctionType::isVariadic; unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); } typedef const QualType *arg_type_iterator; @@ -2361,10 +2387,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, arg_type_iterator ArgTys, unsigned NumArgs, - bool isVariadic, unsigned TypeQuals, - bool hasExceptionSpec, bool anyExceptionSpec, - unsigned NumExceptions, exception_iterator Exs, - ExtInfo ExtInfo); + const ExtProtoInfo &EPI); }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index dd8ae51e9008..22e395cf9616 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -615,7 +615,7 @@ public: QualType *ParamTypes, unsigned NumParamTypes, bool Variadic, unsigned Quals, SourceLocation Loc, DeclarationName Entity, - const FunctionType::ExtInfo &Info); + FunctionType::ExtInfo Info); QualType BuildMemberPointerType(QualType T, QualType Class, SourceLocation Loc, DeclarationName Entity); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index ecba4a136fc8..a6b0861f0214 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1141,7 +1141,7 @@ QualType ASTContext::getObjCGCQualType(QualType T, } static QualType getExtFunctionType(ASTContext& Context, QualType T, - const FunctionType::ExtInfo &Info) { + const FunctionType::ExtInfo &Info) { QualType ResultType; if (const PointerType *Pointer = T->getAs()) { QualType Pointee = Pointer->getPointeeType(); @@ -1183,15 +1183,11 @@ static QualType getExtFunctionType(ASTContext& Context, QualType T, Info); } else { const FunctionProtoType *FPT = cast(F); - ResultType - = Context.getFunctionType(FPT->getResultType(), FPT->arg_type_begin(), - FPT->getNumArgs(), FPT->isVariadic(), - FPT->getTypeQuals(), - FPT->hasExceptionSpec(), - FPT->hasAnyExceptionSpec(), - FPT->getNumExceptions(), - FPT->exception_begin(), - Info); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.ExtInfo = Info; + ResultType = Context.getFunctionType(FPT->getResultType(), + FPT->arg_type_begin(), + FPT->getNumArgs(), EPI); } } else return T; @@ -1201,20 +1197,17 @@ static QualType getExtFunctionType(ASTContext& Context, QualType T, QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) { FunctionType::ExtInfo Info = getFunctionExtInfo(T); - return getExtFunctionType(*this, T, - Info.withNoReturn(AddNoReturn)); + return getExtFunctionType(*this, T, Info.withNoReturn(AddNoReturn)); } QualType ASTContext::getCallConvType(QualType T, CallingConv CallConv) { FunctionType::ExtInfo Info = getFunctionExtInfo(T); - return getExtFunctionType(*this, T, - Info.withCallingConv(CallConv)); + return getExtFunctionType(*this, T, Info.withCallingConv(CallConv)); } QualType ASTContext::getRegParmType(QualType T, unsigned RegParm) { FunctionType::ExtInfo Info = getFunctionExtInfo(T); - return getExtFunctionType(*this, T, - Info.withRegParm(RegParm)); + return getExtFunctionType(*this, T, Info.withRegParm(RegParm)); } /// getComplexType - Return the uniqued reference to the type for a complex @@ -1763,20 +1756,13 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, /// getFunctionType - Return a normal function type with a typed argument /// list. isVariadic indicates whether the argument list includes '...'. -QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, - unsigned NumArgs, bool isVariadic, - unsigned TypeQuals, bool hasExceptionSpec, - bool hasAnyExceptionSpec, unsigned NumExs, - const QualType *ExArray, - const FunctionType::ExtInfo &Info) { - - const CallingConv CallConv= Info.getCC(); +QualType ASTContext::getFunctionType(QualType ResultTy, + const QualType *ArgArray, unsigned NumArgs, + const FunctionProtoType::ExtProtoInfo &EPI) { // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; - FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic, - TypeQuals, hasExceptionSpec, hasAnyExceptionSpec, - NumExs, ExArray, Info); + FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI); void *InsertPos = 0; if (FunctionProtoType *FTP = @@ -1784,11 +1770,13 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, return QualType(FTP, 0); // Determine whether the type being created is already canonical or not. - bool isCanonical = !hasExceptionSpec && ResultTy.isCanonical(); + bool isCanonical = !EPI.HasExceptionSpec && ResultTy.isCanonical(); for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; + const CallingConv CallConv = EPI.ExtInfo.getCC(); + // If this type isn't canonical, get the canonical version of it. // The exception spec is not part of the canonical type. QualType Canonical; @@ -1798,11 +1786,18 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, for (unsigned i = 0; i != NumArgs; ++i) CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i])); + FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI; + if (CanonicalEPI.HasExceptionSpec) { + CanonicalEPI.HasExceptionSpec = false; + CanonicalEPI.HasAnyExceptionSpec = false; + CanonicalEPI.NumExceptions = 0; + } + CanonicalEPI.ExtInfo + = CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv)); + Canonical = getFunctionType(getCanonicalType(ResultTy), CanonicalArgs.data(), NumArgs, - isVariadic, TypeQuals, false, - false, 0, 0, - Info.withCallingConv(getCanonicalCallConv(CallConv))); + CanonicalEPI); // Get the new insert position for the node we care about. FunctionProtoType *NewIP = @@ -1813,13 +1808,11 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, // FunctionProtoType objects are allocated with extra bytes after 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) + - NumExs*sizeof(QualType), TypeAlignment); - new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic, - TypeQuals, hasExceptionSpec, hasAnyExceptionSpec, - ExArray, NumExs, Canonical, Info); + size_t Size = sizeof(FunctionProtoType) + + NumArgs * sizeof(QualType) + + EPI.NumExceptions * sizeof(QualType); + FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); + new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, EPI); Types.push_back(FTP); FunctionProtoTypes.InsertNode(FTP, InsertPos); return QualType(FTP, 0); @@ -4852,6 +4845,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (!isSameCallConv(lcc, rcc)) return QualType(); + FunctionType::ExtInfo einfo = FunctionType::ExtInfo(NoReturn, RegParm, lcc); + if (lproto && rproto) { // two C99 style function prototypes assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() && "C++ shouldn't be here"); @@ -4895,10 +4890,10 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, } if (allLTypes) return lhs; if (allRTypes) return rhs; - return getFunctionType(retType, types.begin(), types.size(), - lproto->isVariadic(), lproto->getTypeQuals(), - false, false, 0, 0, - FunctionType::ExtInfo(NoReturn, RegParm, lcc)); + + FunctionProtoType::ExtProtoInfo EPI = lproto->getExtProtoInfo(); + EPI.ExtInfo = einfo; + return getFunctionType(retType, types.begin(), types.size(), EPI); } if (lproto) allRTypes = false; @@ -4929,11 +4924,11 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (allLTypes) return lhs; if (allRTypes) return rhs; + + FunctionProtoType::ExtProtoInfo EPI = proto->getExtProtoInfo(); + EPI.ExtInfo = einfo; return getFunctionType(retType, proto->arg_type_begin(), - proto->getNumArgs(), proto->isVariadic(), - proto->getTypeQuals(), - false, false, 0, 0, - FunctionType::ExtInfo(NoReturn, RegParm, lcc)); + proto->getNumArgs(), EPI); } if (allLTypes) return lhs; @@ -5218,16 +5213,11 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { // In either case, use OldReturnType to build the new function type. const FunctionType *F = LHS->getAs(); if (const FunctionProtoType *FPT = cast(F)) { - FunctionType::ExtInfo Info = getFunctionExtInfo(LHS); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.ExtInfo = getFunctionExtInfo(LHS); QualType ResultType = getFunctionType(OldReturnType, FPT->arg_type_begin(), - FPT->getNumArgs(), FPT->isVariadic(), - FPT->getTypeQuals(), - FPT->hasExceptionSpec(), - FPT->hasAnyExceptionSpec(), - FPT->getNumExceptions(), - FPT->exception_begin(), - Info); + FPT->getNumArgs(), EPI); return ResultType; } } @@ -5580,10 +5570,11 @@ QualType ASTContext::GetBuiltinType(unsigned Id, if (ArgTypes.size() == 0 && TypeStr[0] == '.') return getFunctionNoProtoType(ResType); + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = (TypeStr[0] == '.'); // FIXME: Should we create noreturn types? - return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(), - TypeStr[0] == '.', 0, false, false, 0, 0, - FunctionType::ExtInfo()); + + return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(), EPI); } GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 8415977349b3..cc485c47d9f0 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1473,16 +1473,12 @@ QualType ASTNodeImporter::VisitFunctionProtoType(FunctionProtoType *T) { return QualType(); ExceptionTypes.push_back(ExceptionType); } + + FunctionProtoType::ExtProtoInfo EPI = T->getExtProtoInfo(); + EPI.Exceptions = ExceptionTypes.data(); return Importer.getToContext().getFunctionType(ToResultType, ArgTypes.data(), - ArgTypes.size(), - T->isVariadic(), - T->getTypeQuals(), - T->hasExceptionSpec(), - T->hasAnyExceptionSpec(), - ExceptionTypes.size(), - ExceptionTypes.data(), - T->getExtInfo()); + ArgTypes.size(), EPI); } QualType ASTNodeImporter::VisitTypedefType(TypedefType *T) { diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index b67e82453dcc..1c134608a508 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -185,6 +185,25 @@ PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info) Location = Info->getTypeLoc().getLocalSourceRange().getBegin(); } +CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context, + Expr *Base, bool isArrow, SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc, + SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType) + : Expr(CXXPseudoDestructorExprClass, + Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, + FunctionProtoType::ExtProtoInfo())), + VK_RValue, OK_Ordinary, + /*isTypeDependent=*/(Base->isTypeDependent() || + (DestroyedType.getTypeSourceInfo() && + DestroyedType.getTypeSourceInfo()->getType()->isDependentType())), + /*isValueDependent=*/Base->isValueDependent()), + Base(static_cast(Base)), IsArrow(isArrow), + OperatorLoc(OperatorLoc), Qualifier(Qualifier), + QualifierRange(QualifierRange), + ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc), + DestroyedType(DestroyedType) { } + QualType CXXPseudoDestructorExpr::getDestroyedType() const { if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo()) return TInfo->getType(); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 127613ed32ea..25aa5e0ea144 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1097,65 +1097,55 @@ llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) { return ""; } -FunctionProtoType::FunctionProtoType(QualType Result, const QualType *ArgArray, - unsigned numArgs, bool isVariadic, - unsigned typeQuals, bool hasExs, - bool hasAnyExs, const QualType *ExArray, - unsigned numExs, QualType Canonical, - const ExtInfo &Info) - : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical, - Result->isDependentType(), - Result->isVariablyModifiedType(), - Result->containsUnexpandedParameterPack(), - Info), - NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs), - AnyExceptionSpec(hasAnyExs) +FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, + unsigned numArgs, QualType canonical, + const ExtProtoInfo &epi) + : FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals, canonical, + result->isDependentType(), + result->isVariablyModifiedType(), + result->containsUnexpandedParameterPack(), + epi.ExtInfo), + NumArgs(numArgs), NumExceptions(epi.NumExceptions), + HasExceptionSpec(epi.HasExceptionSpec), + HasAnyExceptionSpec(epi.HasAnyExceptionSpec) { // Fill in the trailing argument array. - QualType *ArgInfo = reinterpret_cast(this+1); + QualType *argSlot = reinterpret_cast(this+1); for (unsigned i = 0; i != numArgs; ++i) { - if (ArgArray[i]->isDependentType()) + if (args[i]->isDependentType()) setDependent(); - if (ArgArray[i]->containsUnexpandedParameterPack()) + if (args[i]->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); - ArgInfo[i] = ArgArray[i]; + argSlot[i] = args[i]; } // Fill in the exception array. - QualType *Ex = ArgInfo + numArgs; - for (unsigned i = 0; i != numExs; ++i) - Ex[i] = ExArray[i]; + QualType *exnSlot = argSlot + numArgs; + for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) + exnSlot[i] = epi.Exceptions[i]; } void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, - arg_type_iterator ArgTys, - unsigned NumArgs, bool isVariadic, - unsigned TypeQuals, bool hasExceptionSpec, - bool anyExceptionSpec, unsigned NumExceptions, - exception_iterator Exs, - FunctionType::ExtInfo Info) { + const QualType *ArgTys, unsigned NumArgs, + const ExtProtoInfo &epi) { 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()); + ID.AddBoolean(epi.Variadic); + ID.AddInteger(epi.TypeQuals); + if (epi.HasExceptionSpec) { + ID.AddBoolean(epi.HasAnyExceptionSpec); + for (unsigned i = 0; i != epi.NumExceptions; ++i) + ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr()); } - Info.Profile(ID); + epi.ExtInfo.Profile(ID); } void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getResultType(), arg_type_begin(), NumArgs, isVariadic(), - getTypeQuals(), hasExceptionSpec(), hasAnyExceptionSpec(), - getNumExceptions(), exception_begin(), - getExtInfo()); + Profile(ID, getResultType(), arg_type_begin(), NumArgs, getExtProtoInfo()); } QualType TypedefType::desugar() const { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 7bd0c3da9ea7..8a0d78cc217c 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -250,13 +250,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, Builder.SetInsertPoint(EntryBB); - QualType FnType = getContext().getFunctionType(RetTy, 0, 0, false, 0, - false, false, 0, 0, - /*FIXME?*/ - FunctionType::ExtInfo()); - // Emit subprogram debug descriptor. if (CGDebugInfo *DI = getDebugInfo()) { + // FIXME: what is going on here and why does it ignore all these + // interesting type properties? + QualType FnType = + getContext().getFunctionType(RetTy, 0, 0, + FunctionProtoType::ExtProtoInfo()); + DI->setLocation(StartLoc); DI->EmitFunctionStart(GD, FnType, CurFn, Builder); } diff --git a/clang/lib/Rewrite/RewriteObjC.cpp b/clang/lib/Rewrite/RewriteObjC.cpp index 0d3881197bbe..539ee49a6c4e 100644 --- a/clang/lib/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Rewrite/RewriteObjC.cpp @@ -450,6 +450,15 @@ namespace { To += From[i]; } } + + QualType getSimpleFunctionType(QualType result, + const QualType *args, + unsigned numArgs, + bool variadic = false) { + FunctionProtoType::ExtProtoInfo fpi; + fpi.Variadic = variadic; + return Context->getFunctionType(result, args, numArgs, fpi); + } }; // Helper function: create a CStyleCastExpr with trivial type source info. @@ -2352,11 +2361,8 @@ void RewriteObjC::SynthSelGetUidFunctionDecl() { IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); llvm::SmallVector ArgTys; ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); - QualType getFuncType = Context->getFunctionType(Context->getObjCSelType(), - &ArgTys[0], ArgTys.size(), - false /*isVariadic*/, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType getFuncType = + getSimpleFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size()); SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SelGetUidIdent, getFuncType, 0, @@ -2451,11 +2457,8 @@ void RewriteObjC::SynthSuperContructorFunctionDecl() { assert(!argT.isNull() && "Can't find 'id' type"); ArgTys.push_back(argT); ArgTys.push_back(argT); - QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), - &ArgTys[0], ArgTys.size(), - false, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), + &ArgTys[0], ArgTys.size()); SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, @@ -2473,11 +2476,9 @@ void RewriteObjC::SynthMsgSendFunctionDecl() { argT = Context->getObjCSelType(); assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); - QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), - &ArgTys[0], ArgTys.size(), - true /*isVariadic*/, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), + &ArgTys[0], ArgTys.size(), + true /*isVariadic*/); MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, @@ -2498,11 +2499,9 @@ void RewriteObjC::SynthMsgSendSuperFunctionDecl() { argT = Context->getObjCSelType(); assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); - QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), - &ArgTys[0], ArgTys.size(), - true /*isVariadic*/, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), + &ArgTys[0], ArgTys.size(), + true /*isVariadic*/); MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, @@ -2520,11 +2519,9 @@ void RewriteObjC::SynthMsgSendStretFunctionDecl() { argT = Context->getObjCSelType(); assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); - QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), - &ArgTys[0], ArgTys.size(), - true /*isVariadic*/, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), + &ArgTys[0], ArgTys.size(), + true /*isVariadic*/); MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, @@ -2547,11 +2544,9 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { argT = Context->getObjCSelType(); assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); - QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), - &ArgTys[0], ArgTys.size(), - true /*isVariadic*/, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), + &ArgTys[0], ArgTys.size(), + true /*isVariadic*/); MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, @@ -2569,11 +2564,9 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() { argT = Context->getObjCSelType(); assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); - QualType msgSendType = Context->getFunctionType(Context->DoubleTy, - &ArgTys[0], ArgTys.size(), - true /*isVariadic*/, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, + &ArgTys[0], ArgTys.size(), + true /*isVariadic*/); MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, @@ -2586,11 +2579,8 @@ void RewriteObjC::SynthGetClassFunctionDecl() { IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); llvm::SmallVector ArgTys; ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); - QualType getClassType = Context->getFunctionType(Context->getObjCIdType(), - &ArgTys[0], ArgTys.size(), - false /*isVariadic*/, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), + &ArgTys[0], ArgTys.size()); GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), getClassIdent, getClassType, 0, @@ -2604,11 +2594,8 @@ void RewriteObjC::SynthGetSuperClassFunctionDecl() { &Context->Idents.get("class_getSuperclass"); llvm::SmallVector ArgTys; ArgTys.push_back(Context->getObjCClassType()); - QualType getClassType = Context->getFunctionType(Context->getObjCClassType(), - &ArgTys[0], ArgTys.size(), - false /*isVariadic*/, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), + &ArgTys[0], ArgTys.size()); GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), getSuperClassIdent, @@ -2623,11 +2610,8 @@ void RewriteObjC::SynthGetMetaClassFunctionDecl() { IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); llvm::SmallVector ArgTys; ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); - QualType getClassType = Context->getFunctionType(Context->getObjCIdType(), - &ArgTys[0], ArgTys.size(), - false /*isVariadic*/, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), + &ArgTys[0], ArgTys.size()); GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), getClassIdent, getClassType, 0, @@ -3075,12 +3059,10 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, CK_BitCast, DRE); // Now do the "normal" pointer to function cast. - QualType castType = Context->getFunctionType(returnType, - &ArgTypes[0], ArgTypes.size(), - // If we don't have a method decl, force a variadic cast. - Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType castType = + getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), + // If we don't have a method decl, force a variadic cast. + Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true); castType = Context->getPointerType(castType); cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, cast); @@ -3108,11 +3090,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, Context->getPointerType(Context->VoidTy), CK_BitCast, STDRE); // Now do the "normal" pointer to function cast. - castType = Context->getFunctionType(returnType, - &ArgTypes[0], ArgTypes.size(), - Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), + Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false); castType = Context->getPointerType(castType); cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, cast); @@ -4649,9 +4628,7 @@ QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) { // FIXME. Does this work if block takes no argument but has a return type // which is of block type? if (HasBlockType) - FuncType = Context->getFunctionType(Res, - &ArgTypes[0], ArgTypes.size(), false/*no variadic*/, 0, - false, false, 0, 0, FunctionType::ExtInfo()); + FuncType = getSimpleFunctionType(Res, &ArgTypes[0], ArgTypes.size()); else FuncType = QualType(FT, 0); return FuncType; } @@ -4719,10 +4696,8 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { } } // Now do the pointer to function cast. - QualType PtrToFuncCastType = Context->getFunctionType(Exp->getType(), - &ArgTypes[0], ArgTypes.size(), false/*no variadic*/, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); + QualType PtrToFuncCastType + = getSimpleFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size()); PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 403838176c63..66e517008caf 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1285,10 +1285,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { OldProto->arg_type_end()); NewQType = Context.getFunctionType(NewFuncType->getResultType(), ParamTypes.data(), ParamTypes.size(), - OldProto->isVariadic(), - OldProto->getTypeQuals(), - false, false, 0, 0, - OldProto->getExtInfo()); + OldProto->getExtProtoInfo()); New->setType(NewQType); New->setHasInheritedPrototype(); @@ -1370,9 +1367,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0], ArgTypes.size(), - OldProto->isVariadic(), 0, - false, false, 0, 0, - OldProto->getExtInfo())); + OldProto->getExtProtoInfo())); return MergeCompatibleFunctionDecls(New, Old); } @@ -4046,9 +4041,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Turn this into a variadic function with no parameters. const FunctionType *FT = NewFD->getType()->getAs(); - QualType R = Context.getFunctionType(FT->getResultType(), - 0, 0, true, 0, false, false, 0, 0, - FT->getExtInfo()); + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = true; + EPI.ExtInfo = FT->getExtInfo(); + + QualType R = Context.getFunctionType(FT->getResultType(), 0, 0, EPI); NewFD->setType(R); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 3cfde26d24b0..eec80f0d5a4b 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2851,20 +2851,21 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, if (FTI.TypeQuals & Qualifiers::Restrict) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) << "restrict" << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); } // Rebuild the function type "R" without any type qualifiers (in // case any of the errors above fired) and with "void" as the // return type, since constructors don't have return types. const FunctionProtoType *Proto = R->getAs(); + if (Proto->getResultType() == Context.VoidTy && !D.isInvalidType()) + return R; + + FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); + EPI.TypeQuals = 0; + return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(), - Proto->getNumArgs(), - Proto->isVariadic(), 0, - Proto->hasExceptionSpec(), - Proto->hasAnyExceptionSpec(), - Proto->getNumExceptions(), - Proto->exception_begin(), - Proto->getExtInfo()); + Proto->getNumArgs(), EPI); } /// CheckConstructor - Checks a fully-formed constructor for @@ -3022,16 +3023,14 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, // parameters (in case any of the errors above fired) and with // "void" as the return type, since destructors don't have return // types. + if (!D.isInvalidType()) + return R; + const FunctionProtoType *Proto = R->getAs(); - if (!Proto) - return QualType(); - - return Context.getFunctionType(Context.VoidTy, 0, 0, false, 0, - Proto->hasExceptionSpec(), - Proto->hasAnyExceptionSpec(), - Proto->getNumExceptions(), - Proto->exception_begin(), - Proto->getExtInfo()); + FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); + EPI.Variadic = false; + EPI.TypeQuals = 0; + return Context.getFunctionType(Context.VoidTy, 0, 0, EPI); } /// CheckConversionDeclarator - Called by ActOnDeclarator to check the @@ -3111,15 +3110,8 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // Rebuild the function type "R" without any parameters (in case any // of the errors above fired) and with the conversion type as the // return type. - if (D.isInvalidType()) { - R = Context.getFunctionType(ConvType, 0, 0, false, - Proto->getTypeQuals(), - Proto->hasExceptionSpec(), - Proto->hasAnyExceptionSpec(), - Proto->getNumExceptions(), - Proto->exception_begin(), - Proto->getExtInfo()); - } + if (D.isInvalidType()) + R = Context.getFunctionType(ConvType, 0, 0, Proto->getExtProtoInfo()); // C++0x explicit conversion operators. if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x) @@ -4310,7 +4302,12 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( ExceptSpec.CalledDecl(Constructor); } } - + + FunctionProtoType::ExtProtoInfo EPI; + EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); + EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.NumExceptions = ExceptSpec.size(); + EPI.Exceptions = ExceptSpec.data(); // Create the actual constructor declaration. CanQualType ClassType @@ -4321,12 +4318,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo, Context.getFunctionType(Context.VoidTy, - 0, 0, false, 0, - ExceptSpec.hasExceptionSpecification(), - ExceptSpec.hasAnyExceptionSpecification(), - ExceptSpec.size(), - ExceptSpec.data(), - FunctionType::ExtInfo()), + 0, 0, EPI), /*TInfo=*/0, /*isExplicit=*/false, /*isInline=*/true, @@ -4414,13 +4406,12 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { } // Create the actual destructor declaration. - QualType Ty = Context.getFunctionType(Context.VoidTy, - 0, 0, false, 0, - ExceptSpec.hasExceptionSpecification(), - ExceptSpec.hasAnyExceptionSpecification(), - ExceptSpec.size(), - ExceptSpec.data(), - FunctionType::ExtInfo()); + FunctionProtoType::ExtProtoInfo EPI; + EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); + EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.NumExceptions = ExceptSpec.size(); + EPI.Exceptions = ExceptSpec.data(); + QualType Ty = Context.getFunctionType(Context.VoidTy, 0, 0, EPI); CanQualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); @@ -4812,17 +4803,16 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { // An implicitly-declared copy assignment operator is an inline public // member of its class. + FunctionProtoType::ExtProtoInfo EPI; + EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); + EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.NumExceptions = ExceptSpec.size(); + EPI.Exceptions = ExceptSpec.data(); DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create(Context, ClassDecl, NameInfo, - Context.getFunctionType(RetType, &ArgType, 1, - false, 0, - ExceptSpec.hasExceptionSpecification(), - ExceptSpec.hasAnyExceptionSpecification(), - ExceptSpec.size(), - ExceptSpec.data(), - FunctionType::ExtInfo()), + Context.getFunctionType(RetType, &ArgType, 1, EPI), /*TInfo=*/0, /*isStatic=*/false, /*StorageClassAsWritten=*/SC_None, /*isInline=*/true); @@ -5278,6 +5268,11 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // An implicitly-declared copy constructor is an inline public // member of its class. + FunctionProtoType::ExtProtoInfo EPI; + EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); + EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.NumExceptions = ExceptSpec.size(); + EPI.Exceptions = ExceptSpec.data(); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType)); @@ -5285,13 +5280,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo, Context.getFunctionType(Context.VoidTy, - &ArgType, 1, - false, 0, - ExceptSpec.hasExceptionSpecification(), - ExceptSpec.hasAnyExceptionSpecification(), - ExceptSpec.size(), - ExceptSpec.data(), - FunctionType::ExtInfo()), + &ArgType, 1, EPI), /*TInfo=*/0, /*isExplicit=*/false, /*isInline=*/true, diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 885e52dd76a2..d08e84dacd21 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -115,6 +115,9 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification) return true; + const FunctionProtoType *NewProto + = New->getType()->getAs(); + // The new function declaration is only missing an empty exception // specification "throw()". If the throw() specification came from a // function in a system header that has C linkage, just add an empty @@ -123,42 +126,38 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // to many libc functions as an optimization. Unfortunately, that // optimization isn't permitted by the C++ standard, so we're forced // to work around it here. - if (MissingEmptyExceptionSpecification && - isa(New->getType()) && + if (MissingEmptyExceptionSpecification && NewProto && (Old->getLocation().isInvalid() || Context.getSourceManager().isInSystemHeader(Old->getLocation())) && Old->isExternC()) { - const FunctionProtoType *NewProto - = cast(New->getType()); + FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); + EPI.HasExceptionSpec = true; + EPI.HasAnyExceptionSpec = false; + EPI.NumExceptions = 0; QualType NewType = Context.getFunctionType(NewProto->getResultType(), NewProto->arg_type_begin(), NewProto->getNumArgs(), - NewProto->isVariadic(), - NewProto->getTypeQuals(), - true, false, 0, 0, - NewProto->getExtInfo()); + EPI); New->setType(NewType); return false; } - if (MissingExceptionSpecification && isa(New->getType())) { - const FunctionProtoType *NewProto - = cast(New->getType()); + if (MissingExceptionSpecification && NewProto) { const FunctionProtoType *OldProto = Old->getType()->getAs(); + FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); + EPI.HasExceptionSpec = OldProto->hasExceptionSpec(); + EPI.HasAnyExceptionSpec = OldProto->hasAnyExceptionSpec(); + EPI.NumExceptions = OldProto->getNumExceptions(); + EPI.Exceptions = OldProto->exception_begin(); + // Update the type of the function with the appropriate exception // specification. QualType NewType = Context.getFunctionType(NewProto->getResultType(), NewProto->arg_type_begin(), NewProto->getNumArgs(), - NewProto->isVariadic(), - NewProto->getTypeQuals(), - OldProto->hasExceptionSpec(), - OldProto->hasAnyExceptionSpec(), - OldProto->getNumExceptions(), - OldProto->exception_begin(), - NewProto->getExtInfo()); + EPI); New->setType(NewType); // If exceptions are disabled, suppress the warning about missing diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 27e9e62fb3d0..3f114dd6296a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8326,8 +8326,9 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, // Turn protoless block types into nullary block types. if (isa(FTy)) { - BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, - false, false, 0, 0, Ext); + FunctionProtoType::ExtProtoInfo EPI; + EPI.ExtInfo = Ext; + BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI); // Otherwise, if we don't need to change anything about the function type, // preserve its sugar structure. @@ -8338,23 +8339,20 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, // Otherwise, make the minimal modifications to the function type. } else { const FunctionProtoType *FPT = cast(FTy); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.TypeQuals = 0; // FIXME: silently? + EPI.ExtInfo = Ext; BlockTy = Context.getFunctionType(RetTy, FPT->arg_type_begin(), FPT->getNumArgs(), - FPT->isVariadic(), - /*quals*/ 0, - FPT->hasExceptionSpec(), - FPT->hasAnyExceptionSpec(), - FPT->getNumExceptions(), - FPT->exception_begin(), - Ext); + EPI); } // If we don't have a function type, just build one from nothing. } else { - BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, - false, false, 0, 0, - FunctionType::ExtInfo(NoReturn, 0, CC_Default)); + FunctionProtoType::ExtProtoInfo EPI; + EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, 0, CC_Default); + BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI); } DiagnoseUnusedParameters(BSI->TheDecl->param_begin(), diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 41a342942c8a..76fcaeae58d9 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1074,21 +1074,24 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // To perform this comparison, we compute the function type that // the deallocation function should have, and use that type both // for template argument deduction and for comparison purposes. + // + // FIXME: this comparison should ignore CC and the like. QualType ExpectedFunctionType; { const FunctionProtoType *Proto = OperatorNew->getType()->getAs(); + llvm::SmallVector ArgTypes; ArgTypes.push_back(Context.VoidPtrTy); for (unsigned I = 1, N = Proto->getNumArgs(); I < N; ++I) ArgTypes.push_back(Proto->getArgType(I)); + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = Proto->isVariadic(); + ExpectedFunctionType = Context.getFunctionType(Context.VoidTy, ArgTypes.data(), - ArgTypes.size(), - Proto->isVariadic(), - 0, false, false, 0, 0, - FunctionType::ExtInfo()); + ArgTypes.size(), EPI); } for (LookupResult::iterator D = FoundDelete.begin(), @@ -1340,12 +1343,15 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, assert(StdBadAlloc && "Must have std::bad_alloc declared"); BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); } + + FunctionProtoType::ExtProtoInfo EPI; + EPI.HasExceptionSpec = true; + if (HasBadAllocExceptionSpec) { + EPI.NumExceptions = 1; + EPI.Exceptions = &BadAllocType; + } - QualType FnType = Context.getFunctionType(Return, &Argument, 1, false, 0, - true, false, - HasBadAllocExceptionSpec? 1 : 0, - &BadAllocType, - FunctionType::ExtInfo()); + QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI); FunctionDecl *Alloc = FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name, FnType, /*TInfo=*/0, SC_None, diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 6ff9cc69f1cf..d4db84b7761c 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -671,13 +671,14 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { // Compute the type of the function that we would expect the conversion // function to have, if it were to match the name given. // FIXME: Calling convention! - FunctionType::ExtInfo ConvProtoInfo = ConvProto->getExtInfo(); + FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo(); + EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default); + EPI.HasExceptionSpec = false; + EPI.HasAnyExceptionSpec = false; + EPI.NumExceptions = 0; QualType ExpectedType = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(), - 0, 0, ConvProto->isVariadic(), - ConvProto->getTypeQuals(), - false, false, 0, 0, - ConvProtoInfo.withCallingConv(CC_Default)); + 0, 0, EPI); // Perform template argument deduction against the type that we would // expect the function to have. diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 31692fc1f2ee..2f73991ec56d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1995,19 +1995,20 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, // Rebuild the function type + FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); + EPI.HasExceptionSpec = Proto->hasExceptionSpec(); + EPI.HasAnyExceptionSpec = Proto->hasAnyExceptionSpec(); + EPI.NumExceptions = Exceptions.size(); + EPI.Exceptions = Exceptions.data(); + EPI.ExtInfo = Proto->getExtInfo(); + const FunctionProtoType *NewProto = New->getType()->getAs(); assert(NewProto && "Template instantiation without function prototype?"); New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(), NewProto->arg_type_begin(), NewProto->getNumArgs(), - NewProto->isVariadic(), - NewProto->getTypeQuals(), - Proto->hasExceptionSpec(), - Proto->hasAnyExceptionSpec(), - Exceptions.size(), - Exceptions.data(), - Proto->getExtInfo())); + EPI)); } SemaRef.InstantiateAttrs(TemplateArgs, Tmpl, New); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 23c159fbc5ad..2a75ff0b3406 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -829,7 +829,7 @@ QualType Sema::BuildFunctionType(QualType T, unsigned NumParamTypes, bool Variadic, unsigned Quals, SourceLocation Loc, DeclarationName Entity, - const FunctionType::ExtInfo &Info) { + FunctionType::ExtInfo Info) { if (T->isArrayType() || T->isFunctionType()) { Diag(Loc, diag::err_func_returning_array_function) << T->isFunctionType() << T; @@ -850,8 +850,12 @@ QualType Sema::BuildFunctionType(QualType T, if (Invalid) return QualType(); - return Context.getFunctionType(T, ParamTypes, NumParamTypes, Variadic, - Quals, false, false, 0, 0, Info); + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = Variadic; + EPI.TypeQuals = Quals; + EPI.ExtInfo = Info; + + return Context.getFunctionType(T, ParamTypes, NumParamTypes, EPI); } /// \brief Build a member pointer type \c T Class::*. @@ -1265,6 +1269,10 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; } + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = FTI.isVariadic; + EPI.TypeQuals = FTI.TypeQuals; + // Otherwise, we have a function with an argument list that is // potentially variadic. llvm::SmallVector ArgTys; @@ -1316,22 +1324,23 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } llvm::SmallVector Exceptions; - Exceptions.reserve(FTI.NumExceptions); - for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { - // FIXME: Preserve type source info. - QualType ET = GetTypeFromParser(FTI.Exceptions[ei].Ty); - // Check that the type is valid for an exception spec, and drop it if - // not. - if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range)) - Exceptions.push_back(ET); + if (FTI.hasExceptionSpec) { + EPI.HasExceptionSpec = FTI.hasExceptionSpec; + EPI.HasAnyExceptionSpec = FTI.hasAnyExceptionSpec; + EPI.NumExceptions = FTI.NumExceptions; + Exceptions.reserve(FTI.NumExceptions); + for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { + // FIXME: Preserve type source info. + QualType ET = GetTypeFromParser(FTI.Exceptions[ei].Ty); + // Check that the type is valid for an exception spec, and + // drop it if not. + if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range)) + Exceptions.push_back(ET); + } + EPI.Exceptions = Exceptions.data(); } - T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), - FTI.isVariadic, FTI.TypeQuals, - FTI.hasExceptionSpec, - FTI.hasAnyExceptionSpec, - Exceptions.size(), Exceptions.data(), - FunctionType::ExtInfo()); + T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI); } // For GCC compatibility, we allow attributes that apply only to @@ -1437,9 +1446,11 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, << FreeFunction; // Strip the cv-quals from the type. + FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo(); + EPI.TypeQuals = 0; + T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(), - FnTy->getNumArgs(), FnTy->isVariadic(), 0, - false, false, 0, 0, FunctionType::ExtInfo()); + FnTy->getNumArgs(), EPI); } } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 5fe95bfed465..098f71a529a7 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2842,28 +2842,29 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { case TYPE_FUNCTION_PROTO: { QualType ResultType = GetType(Record[0]); - bool NoReturn = Record[1]; - unsigned RegParm = Record[2]; - CallingConv CallConv = (CallingConv)Record[3]; + + FunctionProtoType::ExtProtoInfo EPI; + EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1], + /*regparm*/ Record[2], + static_cast(Record[3])); + unsigned Idx = 4; unsigned NumParams = Record[Idx++]; llvm::SmallVector ParamTypes; for (unsigned I = 0; I != NumParams; ++I) 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++]; + + EPI.Variadic = Record[Idx++]; + EPI.TypeQuals = Record[Idx++]; + EPI.HasExceptionSpec = Record[Idx++]; + EPI.HasAnyExceptionSpec = Record[Idx++]; + EPI.NumExceptions = Record[Idx++]; llvm::SmallVector Exceptions; - for (unsigned I = 0; I != NumExceptions; ++I) + for (unsigned I = 0; I != EPI.NumExceptions; ++I) Exceptions.push_back(GetType(Record[Idx++])); + EPI.Exceptions = Exceptions.data(); return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams, - isVariadic, Quals, hasExceptionSpec, - hasAnyExceptionSpec, NumExceptions, - Exceptions.data(), - FunctionType::ExtInfo(NoReturn, RegParm, - CallConv)); + EPI); } case TYPE_UNRESOLVED_USING: