diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 67 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 10 |
2 files changed, 40 insertions, 37 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e6a89461b45..1db768b28a6 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5897,23 +5897,40 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, << DeclSpec::getSpecifierName(TSCS); // Do not allow returning a objc interface by-value. - if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) { + bool NeedsAdjustment = false; + const FunctionType *FT = R->castAs<FunctionType>(); + QualType ResultTy = FT->getResultType(); + if (ResultTy->isObjCObjectType()) { Diag(D.getIdentifierLoc(), - diag::err_object_cannot_be_passed_returned_by_value) << 0 - << R->getAs<FunctionType>()->getResultType() - << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*"); + diag::err_object_cannot_be_passed_returned_by_value) << 0 << ResultTy + << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*"); + ResultTy = Context.getObjCObjectPointerType(ResultTy); + NeedsAdjustment = true; + } - QualType T = R->getAs<FunctionType>()->getResultType(); - T = Context.getObjCObjectPointerType(T); - if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) { + // Adjust parameter types from the type as written. + SmallVector<QualType, 16> AdjustedParms; + const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT); + if (FPT) { + for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(), + E = FPT->arg_type_end(); I != E; ++I) { + AdjustedParms.push_back(Context.getAdjustedParameterType(*I)); + if (AdjustedParms.back() != *I) + NeedsAdjustment = true; + } + } + + // Skip the type recreation if it isn't needed, for performance and to avoid + // prematurely desugaring things like typedefs and __typeofs. + if (NeedsAdjustment) { + if (FPT) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - R = Context.getFunctionType(T, - ArrayRef<QualType>(FPT->arg_type_begin(), - FPT->getNumArgs()), - EPI); + R = Context.getFunctionType(ResultTy, AdjustedParms, EPI); + } else { + assert(isa<FunctionNoProtoType>(FT)); + FunctionType::ExtInfo EI = FT->getExtInfo(); + R = Context.getFunctionNoProtoType(ResultTy, EI); } - else if (isa<FunctionNoProtoType>(R)) - R = Context.getFunctionNoProtoType(T); } bool isFriend = false; @@ -8498,27 +8515,15 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, SourceLocation NameLoc, IdentifierInfo *Name, QualType T, TypeSourceInfo *TSInfo, VarDecl::StorageClass StorageClass) { - // In ARC, infer a lifetime qualifier for appropriate parameter types. + // Diagnose non-const parameter arrays of ARC types. if (getLangOpts().ObjCAutoRefCount && T.getObjCLifetime() == Qualifiers::OCL_None && - T->isObjCLifetimeType()) { - - Qualifiers::ObjCLifetime lifetime; - - // Special cases for arrays: - // - if it's const, use __unsafe_unretained - // - otherwise, it's an error - if (T->isArrayType()) { - if (!T.isConstQualified()) { - DelayedDiagnostics.add( - sema::DelayedDiagnostic::makeForbiddenType( + T->isObjCLifetimeType() && + T->isArrayType() && + !T.isConstQualified()) { + DelayedDiagnostics.add( + sema::DelayedDiagnostic::makeForbiddenType( NameLoc, diag::err_arc_array_param_no_ownership, T, false)); - } - lifetime = Qualifiers::OCL_ExplicitNone; - } else { - lifetime = T->getObjCARCImplicitLifetime(); - } - T = Context.getLifetimeQualifiedType(T, lifetime); } ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name, diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index e27d627d3ff..977294bd461 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1674,7 +1674,7 @@ QualType Sema::BuildFunctionType(QualType T, bool Invalid = false; for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) { // FIXME: Loc is too inprecise here, should use proper locations for args. - QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]); + QualType ParamType = ParamTypes[Idx]; if (ParamType->isVoidType()) { Diag(Loc, diag::err_param_with_void_type); Invalid = true; @@ -2798,13 +2798,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param); - QualType ArgTy = Param->getType(); + // Get the type as written. It will be adjusted later in + // ActOnFunctionDeclarator(). + QualType ArgTy = Param->getTypeSourceInfo()->getType(); assert(!ArgTy.isNull() && "Couldn't parse type?"); - // Adjust the parameter type. - assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) && - "Unadjusted type?"); - // Look for 'void'. void is allowed only as a single argument to a // function with no other parameters (C99 6.7.5.3p10). We record // int(void) as a FunctionProtoType with an empty argument list. |