summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp15
-rw-r--r--clang/lib/AST/Type.cpp6
-rw-r--r--clang/lib/Sema/SemaDecl.cpp67
-rw-r--r--clang/lib/Sema/SemaType.cpp10
4 files changed, 59 insertions, 39 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 44ff94e3584..384164167db 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -4142,6 +4142,21 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
}
QualType ASTContext::getAdjustedParameterType(QualType T) const {
+ // In ARC, infer a lifetime qualifier for appropriate parameter types.
+ if (getLangOpts().ObjCAutoRefCount &&
+ T.getObjCLifetime() == Qualifiers::OCL_None &&
+ T->isObjCLifetimeType()) {
+ // Special cases for arrays:
+ // - if it's const, use __unsafe_unretained
+ // - otherwise, it's an error
+ Qualifiers::ObjCLifetime lifetime;
+ if (T->isArrayType())
+ lifetime = Qualifiers::OCL_ExplicitNone;
+ else
+ lifetime = T->getObjCARCImplicitLifetime();
+ T = getLifetimeQualifiedType(T, lifetime);
+ }
+
// C99 6.7.5.3p7:
// A declaration of a parameter as "array of type" shall be
// adjusted to "qualified pointer to type", where the type
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index c32df11b667..2c5233bce67 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -1781,8 +1781,10 @@ bool TypeOfExprType::isSugared() const {
}
QualType TypeOfExprType::desugar() const {
- if (isSugared())
- return getUnderlyingExpr()->getType();
+ if (isSugared()) {
+ Expr *E = getUnderlyingExpr();
+ return E->getType();
+ }
return QualType(this, 0);
}
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.
OpenPOWER on IntegriCloud